我正在构建一个简单的指令,我有一个自定义元素,作为
<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和所有者初始化问题,并且稍后可以使用控制器外部更改所有者。
答案 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);
}
});
希望这有所帮助。