Почему мне нужно вызывать $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));

Это приведет к тому, что ваш вызов функции будет применен и автоматически активирует дайджест.