在开始angularjs中调用的指令中的Scope.watch

时间:2014-12-23 20:09:15

标签: javascript angularjs variables angularjs-directive angularjs-scope

我正在构建一个简单的指令,我有一个自定义元素,作为

<button ng-click="change()">Change owner</button>
<problem id="id" owner="owner"></problem>

我想通过按钮点击更改问题的所有者,所以这里是在我的控制器中:

$scope.change = function() {
    $scope.owner = "12390898";
}

我的指令代码如下:

app.directive('problem', function() {
    return {
        restrict: 'E',
        scope: {
            owner: '=owner',
            id: "=id",
        },
        templateUrl: "partials/directives/problem.html",
        controller: function($scope) {
            $scope.$watch("id", function(newValue, oldValue) {
                console.log("id ->", oldValue, " --> ", newValue);
            });

            $scope.$watch("owner", function(newValue, oldValue) {
                console.log("owner ->", oldValue, " --> ", newValue);
            });
        },
        link: function(scope, element, attrs) {

        }
    }
});

但是,控制台输出是:

// At initial load
id -> 1230312  -->  1230312
owner -> 548dfa6accfc105ae415f0e7  -->  548dfa6accfc105ae415f0e7
// After the click
owner -> 548dfa6accfc105ae415f0e7  -->  12390898

为什么在开始时调用它?值是相同的。这是执行以下操作的正确方法吗?:我想在开始时使用默认ID和所有者初始化问题,并且稍后可以使用控制器外部更改所有者。

2 个答案:

答案 0 :(得分:1)

根据docs

  

在观察者注册范围后,监听器fn是   异步调用(通过$ evalAsync)来初始化观察者。在   在极少数情况下,这是不可取的,因为在何时调用侦听器   watchExpression的结果没有改变。检测这种情况   在监听器fn中,您可以比较newVal和oldVal。如果   这两个值是相同的(===)然后监听器被调用   初始化。

这就是手表在一开始就被召唤的原因。点击发生后,再次调用手表,因为值会发生变化。在后续点击中,不应调用监视功能,因为所有者值不再因点击而改变。

如果您只是想允许在父作用域中设置的所有者传递到指令作用域,则双向绑定就足够了。

如果您确实想要对更改的值做出反应,那么手表将是一个简单的选项,可以通知您值正在发生变化。他们现在的手表没有执行任何有价值的功能(即只是console.log输出),所以只是在$ digest循环中进行循环。

回答你的结束问题:

Why is it called at the beginning? The values are same

请参阅上面的文档,其中说明在初始化时调用了watcher函数。

Is it the right approach to do the following?: I want to initialize the problem at the beginning with default id and owner, and be able to change the owner later with controller outside.

通过隔离范围从双向绑定设置中使用id和owner初始化问题。当它们从外部改变时,它们将在指令的隔离范围内更新,反之亦然。

没有手表的样品fiddle

答案 1 :(得分:1)

即使newValue和oldValue相同,也会在编译时调用观察程序内部的侦听器函数。如果您不希望在应用程序加载时执行该功能,您可以将侦听器包装在if语句中,如下所示:

$scope.$watch("id", function(newValue, oldValue) {
     if (newVlaue !== oldValue) {
        console.log("id ->", oldValue, " --> ", newValue);
     }
});

希望这有所帮助。