1

我在从指令中查看范围变量时遇到了一些困难。

我有一个控制器,其范围变量名为 val:

$scope.val = { name: "hello" };

我有一个使用这个值的指令。所以在这个控制器的视图中,我有一些类似的东西:

<custom-component custom-attribute="val"></custom-component>

我已经建立了一个有范围的指令

var myDir = function() {
    return {
        restrict: 'E',
        scope: {
            customAttribute: '=customAttribute'
        },
        link: function(scope, elem, attr) {
            scope.$watch('customAttribute', function(val){ console.log(val); }
        },
        replace: true,
        template:'<div class="hello"></div>'
  };
}

当我第一次运行应用程序时,手表功能很好。现在我在控制器中设置了一个超时并执行以下操作:

setTimeout(function(){
        console.log("Changed chart type name");
        $scope.customAttribute.name="baz";
    },5000);

这不会导致手表功能触发!我不确定问题是什么。我还尝试将超时放在指令链接函数中,以防出现一些对象复制问题(低于 scope.$watch):

link: function(scope, elem, attr) {
        scope.$watch('customAttribute', function(val){ console.log(val); }
        setTimeout(function(){
           console.log("Changed chart type name");
           scope.customAttribute.name="baz";
        },5000);
    },

这还是不行!

编辑:

所以我发现如果在我的控制器中我在更新变量后调用 $scope.$digest() 一切正常。为什么我需要手动调用这个函数?

4

2 回答 2

3

由于您使用的是在角度上下文之外调用的 setTimeout ,因此您必须调用 scope.$apply ,有两种方法可以解决您的问题

1) 使用scope.$apply()

link: function(scope, elem, attr) {
    scope.$watch('customAttribute', function(val){ console.log(val); }
    setTimeout(function(){
       console.log("Changed chart type name");
       scope.customAttribute.name="baz";
       scope.$apply();
    },5000);
},

2)用角度包装函数$timeout

link: function(scope, elem, attr) {
    scope.$watch('customAttribute', function(val){ console.log(val); }
    $timeout(function(){
       console.log("Changed chart type name");
       scope.customAttribute.name="baz";
    },5000);
},
于 2013-07-11T17:43:52.307 回答
3

代替setTimeout, 使用$timeoutAngularJS 等价物。它在内部使用 $scope.$apply。使用setTimeout,事情发生在“Angular World”之外,您的应用程序不知道它们。

不要忘记注入$timeout您的控制器:

.controller('MyCtrl', ['$timeout', function($timeout) {
...

}]);
于 2013-07-11T17:49:08.820 回答