Дебанд ng-model-options не работает на событии размытия, как ожидалось?
Я применил ng-model-options
на input
со следующей конфигурацией
ng-model-options="{updateOn:'default blur',debounce:{default:1000,blur:0}}"
И согласно приложенной конфигурации к ng-model-options
Я ожидаю обновления ng-model's
значение на ng-blur
событие, но оно не возвращает новое значение, несмотря на то, что установлено 0
значение debounce для события blur.
* Примечание: эта проблема возникает, только если пользователь сфокусировался раньше времени, указанного в default
то есть 1000
HTML:
<input type="text" ng-model="myname" ng-blur="onBlur(myname)" ng-model-options="{updateOn:'default blur',debounce:{default:1000,blur:0}}">
<input type="text" ng-model="output"/>
JS:
$scope.myname = "Yogesh";
$scope.output = "";
$scope.onBlur = function(a){
$scope.output = a;
}
Плункерная ссылка: https://embed.plnkr.co/XJMUUD/
Почему debounce не работает? поправьте меня, если я что-то не так делаю!
Заранее спасибо:)
Я также дал ответ на мой вопрос! дайте мне знать, как это гибко использовать и как это поможет сократить циклы дайджеста событий.
3 ответа
Как ng-model-options поможет сократить циклы дайджеста событий?
Да, ng-model-options
может помочь вам ограничить количество $digest
циклы. Если бы вы использовали только ng-модель без установки каких-либо опций для нее, то ваш цикл $ digest будет выполняться для каждого изменения значения ng-модели. Если $digest
цикл заполняется данными, подлежащими грязной проверке, пользователь увидит задержку в пользовательском интерфейсе, в то время как (например) печатает внутри. Вот пример из ссылки на блог toddmotto.
// app.js
angular
.module('app', []);
function trackDigests($rootScope) {
function link($scope, $element, $attrs) {
var count = 0;
function countDigests(newValue, oldValue) {
count++;
$element[0].innerHTML = '$digests: ' + count;
}
$rootScope.$watch(countDigests);
}
return {
restrict: 'EA',
link: link
};
}
angular
.module('app')
.directive('trackDigests', trackDigests);
<script src="//code.angularjs.org/1.4.7/angular.min.js"></script>
<div ng-app="app">
<div>
<form name="myForm">
<h3>Standard <input></h3>
<track-digests></track-digests>
<input
type="text"
name="test"
ng-model="test">
</form>
</div>
</div>
Как вы можете видеть из нашего стандартного ввода, $digest
цикл запускается для каждого символа, который мы вводим в поле ввода. Это может вызвать задержку конечного пользователя для больших приложений.
Теперь мы увидим случай для входов с опциями ng-модели.
// app.js
angular
.module('app', []);
function trackDigests($rootScope) {
function link($scope, $element, $attrs) {
var count = 0;
function countDigests(newValue, oldValue) {
count++;
$element[0].innerHTML = '$digests: ' + count;
}
$rootScope.$watch(countDigests);
}
return {
restrict: 'EA',
link: link
};
}
angular
.module('app')
.directive('trackDigests', trackDigests);
<script src="//code.angularjs.org/1.4.7/angular.min.js"></script>
<div ng-app="app">
<div>
<form name="myForm">
<h3>ngModelOptions <input></h3>
<track-digests></track-digests>
<input
type="text"
name="test"
ng-model="test"
ng-model-options="{
updateOn: 'blur'
}">
</form>
</div>
</div>
Здесь мы можем видеть, что $digest
Цикл срабатывает только тогда, когда мы теряем фокус с ввода. Итак, в основном ngModelOptions
дают нам контроль над тем, как и когда $digest
циклы происходят.
Давайте возьмем еще больший контроль над $digest
цикл, вводя debounce, чтобы мы могли сказать угловые, когда обновлять.
// app.js
angular
.module('app', []);
function trackDigests($rootScope) {
function link($scope, $element, $attrs) {
var count = 0;
function countDigests(newValue, oldValue) {
count++;
$element[0].innerHTML = '$digests: ' + count;
}
$rootScope.$watch(countDigests);
}
return {
restrict: 'EA',
link: link
};
}
angular
.module('app')
.directive('trackDigests', trackDigests);
<script src="//code.angularjs.org/1.4.7/angular.min.js"></script>
<div ng-app="app">
<div>
<form name="myForm">
<h3>ngModelOptions <input></h3>
<track-digests></track-digests>
<input
type="text"
name="test"
ng-model="test"
ng-model-options="{
updateOn: 'default blur',
debounce: {
'default': 250,
'blur': 0
}
}">
</form>
</div>
</div>
Выше показано, что значение по умолчанию будет обновляться через 250 мс после прекращения события, и размытие будет обновляться немедленно, когда пользователь покидает ввод (если это желаемое поведение, которое мы хотим).
Начните вводить снова, затем остановитесь и отметьте $digest
количество значительно ниже, чем первоначальная демонстрация. Затем вы можете нажать / вкладку, чтобы позвонить другому $digest
немедленно.
В чем разница между дефолтом и изменением в debounce?
Значение по умолчанию и изменение свойства объектов debounce - это не что иное, как события. По умолчанию это не событие DOM, это просто часть API ng-model-options. Предположим, вы устанавливаете свои ngModelOptions как
ng-model-options="{
updateOn: 'default'
}"
Тогда не будет никаких изменений в поведении вашего поля ввода по сравнению с поведением по умолчанию. Эта конфигурация не очень полезна, пока мы не объединим ее с
ng-model-options="{
updateOn: 'default',
debounce: { 'default': 500 }
}"
Это сделает ввод для обновления через 500 мс. Так что в основном это отвечает на то, что по умолчанию. Вы можете использовать другие события DOM, такие как change,blur,mouseover
... и т. д. для вашего обсуждения.
Обновление:
Когда вы использовали ng-model-options="{updateOn:'default blur',debounce:{default:1000,blur:0}}"
, ng-blur было запущено со старым значением ng-модели, и после этого были запущены только события updateOn. Так что в основном выходные данные будут содержать старое значение ng-модели, хотя myname будет обновлено.
Рабочий пример: https://plnkr.co/edit/2JPHXvXd992JJ0s37YC9?p=preview
Теперь, когда вы использовали ng-model-options="{updateOn:'default change blur',debounce:{default:1000,blur:0,change:0}}"
, ng-blur было запущено с новым значением ng-model, потому что изменение настройки:0 заставляло события updateOn срабатывать до ng-blur.Таким образом, вывод был обновлен с новым значением ng-model вместе с myname.
Рабочий пример: https://plnkr.co/edit/9wdA0he2YVcsPRLJ1Ant?p=preview
После некоторых исследований мы столкнулись с этой конфигурацией
ng-model-options="{updateOn:'default change blur',debounce:{default:1000,blur:0,change:0}}"
Который работает отлично! как и ожидалось ng-blur
Событие возвращает обновленное значение.
Это потому, что когда вы устанавливаете debounce
Цикл дайджеста запускается по истечении заданного времени. После запуска дайджест-цикла проверяется, изменилось ли значение, которое еще не было синхронизировано в приложении.
В вашем случае входное значение будет синхронизировано с переменной модели myname
через 1000 мс или 1 с, но немедленное обновление при снятии фокуса. Ваш метод onBlur(myname)
вызывается с предыдущим значением myname
потому что в то время, когда была вызвана функция, ей по-прежнему передается предыдущее значение аргумента (она не может обновить значение myname и одновременно вызывать функцию), и после этого обновление цикла дайджеста myname
, Вы можете проверить, что модель обновляется немедленно, поставив {{myname}}
рядом с входами.
ng-blur
-> call onBlur(myname)
-> here myname is with old value still
-> trigger digest loop (here is where the new value is assigned to myname)
-> update model & view
{updateOn: 'event'} указывает, что привязка должна происходить, когда происходит конкретное событие.
Чтобы обновить модель до того, как ваш элемент потеряет фокус (onblur), вы должны использовать updateOn: change
и установите его время равным 0, вот так при каждом изменении angular немедленно свяжет новое значение с параметром вашей функции.