AngularJS:父范围未在指令中更新(使用隔离范围)双向绑定
我有以下代码,它也可以在http://jsfiddle.net/garukun/u69PT/上拨弄。AngularJS:父范围未在指令中更新(使用隔离范围)双向绑定
检视:
<div data-ng-app="testApp">
<div data-ng-controller="testCtrl">
<strong>{{pkey}}</strong>
<span data-test-directive data-parent-item="pkey"
data-parent-update="update(pkey)"></span>
</div>
</div>
JS:
var testApp = angular.module('testApp', []);
testApp.directive('testDirective', function ($timeout) {
return {
scope: {
key: '=parentItem',
parentUpdate: '&'
},
replace: true,
template: '<div><p>{{key}}</p>' +
'<button data-ng-click="lock()">Lock</button>' +
'</div>',
controller: function ($scope, $element, $attrs) {
$scope.lock = function() {
$scope.key = 'D+' + $scope.key;
console.log('DIR :', $scope.key);
// Expecting $scope.$parent.pkey to have also been
// updated before invoking the next line.
$scope.parentUpdate();
// $timeout($scope.parentUpdate); // would work.
};
}
};
});
testApp.controller('testCtrl', function ($scope) {
$scope.pkey = 'golden';
$scope.update = function (k) {
// Expecting local variable k, or $scope.pkey to have been
// updated by calls in the directive's scope.
console.log('CTRL:', $scope.pkey, k);
$scope.pkey = 'C+' + k;
console.log('CTRL:', $scope.pkey);
};
});
基本上,我建立与分离的范围的指令,其中,我双向结合的性质(键)从父范围(pkey)开始,还委派一个方法(parentUpdate)在父范围的上下文中调用。
现在,在指令中的ng-click事件处理程序期间,我想要调用parentUpdate方法并在其中执行某些操作。当我调用该方法时,我期待我的父范围的模型已经更新。但事实上并非如此,这令我感到困惑。
这可能是由于中间缺少$ digest周期,因为用$ timeout包装parentUpdate调用将按预期工作。
难道有人会对缺失的东西有所了解吗?或者如何正确调用parentUpdate?
好吧,我要对这一个进行破解......看起来你正在改变孤立子和父变量,在双向逻辑同步这两个循环的$digest
循环之前。以下是详细信息:
- 首先您的
lock()
函数通过单击按钮来执行。这会更新隔离的$scope.key
变量。 注意:这不是立即更新父母$scope.pKey
;通常会在下一个$digest
周期发生,但在这种情况下不会发生。请继续阅读... - 在
lock()
以内您正在致电parentUpdate()
,它更新了父母的$scope.pKey
变量。 - 然后执行
$digest
循环。当它循环到父范围时,正确检测到对$scope.pKey
的更改。 - 对
$scope.pKey
的更改会触发由隔离范围中的双向绑定创建的watch()
。 These lines是关键的。 - 由隔离范围创建的
watch()
检查双向绑定的值是否与父项的值同步。如果不是(并且在这种情况下不是这样),即使隔离范围的值也发生了变化,并且事实上首先被更改了,但父级的值被复制到隔离范围。
Misko's famous post on Angular data-binding描述了$digest
循环方法的好处。您在这里看到的是$digest
的改变共存的方法的有意识的副作用,其中源代码注释说parent changed and it has precedence
...并且这意味着您的隔离范围的更改会丢失。
你上面提到的$timeout()
方法,通过在第一$digest
周期,使之能够成功复制到父范围,然后调用只改变隔离范围的值避免了这个问题parentUpdate()
通常希望将数据从隔离范围通过表达式传递到父范围,这可以通过将局部变量名称和值的映射传递到表达式包装函数fn来完成。例如,如果表达式是增量(金额),那么我们可以通过调用localFn作为localFn({amount:22})来指定金额值。
这意味着,在步骤#2你可以在你的价值通过一个对象映射像这样通过对pkey
:
parentUpdate({pkey: 'D+' + $scope.key })
下面是更新小提琴:http://jsfiddle.net/KbYcr/
使用$scope.$apply()
代替$scope.$digest()
也起作用。这也会触发rootScope上的摘要。
好的,所以在这里定位一下......你想知道为什么''scope.key ='D +'+ $ scope.key;''lock()'函数似乎没有任何效果, 对? – jandersen