Почему мне нужно вызывать $scope. $Digest() здесь?
Я создал директиву для показа всплывающих подсказок:
app.directive('tooltip',function(){
return{
restrict: 'A',
link: function(scope,element,attr){
element.bind('mouseenter',function(e){
scope.setStyle(e);
});
}
}
});
Соответствующая функция setStyle()
:
$scope.setStyle = function(e){
$scope.style = {
position: 'absolute',
// some other styles
};
$scope.$digest();
};
$scope.style
применяется к этому:
<span ng-style="style">I am a tooltip</span>
который является частью моего представления, обрабатывается контроллером, которому принадлежит $scope.style
Почему мне нужно вызывать $digest()
, чтобы применить изменения к $scope.style
, которые были объявлены и инициализированы ранее?
Ответы
Ответ 1
Поскольку обратный вызов, связанный с событием mouseenter
, находится вне области angular; angular не имеет понятия, когда эта функция запускается/заканчивается, поэтому цикл дайджеста никогда не запускается.
Вызов $digest
или $apply
сообщает angular обновлять привязки и запускать любые часы.
Ответ 2
element.bind()
означает прослушивание определенного события браузера и выполнение обратного вызова, когда это событие отправляется на элемент. Нигде в этой цепочке событий не включен Angular - он не знает, что произошло событие. Поэтому вы должны четко рассказать об этом событии. Однако в большинстве случаев вам следует использовать $scope.$apply()
not $scope.$digest()
, особенно если вы не уверены в этом.
Вот более подходящий код для вашей ситуации:
app.directive('tooltip',function(){
return{
restrict: 'A',
link: function(scope,element,attr){
element.bind('mouseenter',function(e){
scope.setStyle(e);
scope.$apply();
});
}
}
});
и setStyle()
:
$scope.setStyle = function(e){
$scope.style = {
position: 'absolute',
// some other styles
};
};
Ответ 3
$scope.apply() имеет две реализации: одну, которая не имеет аргументов, а другая принимает функцию как аргумент, оценивает ее и вызывает digest(). Использование последнего имеет свои преимущества, поскольку оно завершает вашу функцию в предложении try/catch, которое обрабатывается службой $exceptionHandler.
Хотя вы тоже можете сделать это:
$scope.$apply(scope.setStyle(e));
Это приведет к тому, что ваш вызов функции будет применен и автоматически активирует дайджест.