为什么我必须在这里调用$ scope。$ digest()?

时间:2013-09-13 11:37:34

标签: angularjs data-binding angularjs-directive

我创建了一个显示工具提示的指令:

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,这些更改已在之前声明并初始化?

3 个答案:

答案 0 :(得分:21)

因为附加到mouseenter事件的回调超出了角度的范围; angular不知道该函数何时运行/结束,因此摘要周期永远不会运行。

调用$digest$apply告诉angular更新绑定并触发任何监视。

答案 1 :(得分:12)

element.bind()表示侦听特定的浏览器事件,并在元素上调度此事件时执行回调。在这个事件链中没有任何地方包括Angular - 它不知道事件发生了。因此,您必须明确告诉它事件。但是,在大多数情况下,您应该使用$scope.$apply()而不是$scope.$digest(),尤其是在您不确定时。{/ p>

以下是适合您情况的更合适的代码:

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
    };
};

答案 2 :(得分:1)

$ scope.apply()有两个实现,一个没有参数,另一个接受函数作为参数,计算它并触发digest()。使用后者具有优势,因为它在try / catch子句中包装你的函数,该子句由$ exceptionHandler服务处理。

虽然,你也可以这样做:

$scope.$apply(scope.setStyle(e));

这会将你的函数调用包装为apply并自动触发摘要。