我有以下代码,也可以在http://jsfiddle.net/garukun/u69PT/上摆弄。
查看:
<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)双向绑定属性(key),并且还委托一个方法(parentUpdate)来调用在父范围的上下文中。
现在,在指令中的ng-click事件处理程序中,我想调用parentUpdate方法并在其中执行某些操作。当我调用该方法时,我希望我的父范围的模型已经更新。但实际上,事实并非如此,这让我感到困惑。
这可能是因为中间缺少$ digest周期,因为使用$ timeout包装parentUpdate调用会按预期工作。
有人能否对失踪的内容有所了解?或者如何正确调用parentUpdate?
答案 0 :(得分:27)
好的,我将在这个问题上采取行动......似乎你在$digest
周期之前改变了孤立的子AND和父变量,其中双向逻辑同步两者。这是详细信息:
lock()
功能。这会更新隔离的$scope.key
变量。 注意:这不会立即更新父$scope.pKey
;这通常会发生在下一个$digest
周期,但在这种情况下不会发生。请继续阅读...... lock()
parentUpdate()
内,您正在调用$scope.pKey
来更新父级$digest
变量。$scope.pKey
周期执行。当它循环到父作用域时,可以正确检测到$scope.pKey
的更改。watch()
的更改会触发由隔离范围内的双向绑定创建的watch()
。 These lines是关键的...... $digest
检查双向绑定的值是否与父级的值同步。如果不是(并且不在这种情况下),父级的值将被复制到隔离范围,即使隔离范围的值也已更改,实际上已更改。 Misko's famous post on Angular data-binding描述了$digest
周期方法的好处。你在这里看到的是$timeout()
改变coalesence的方法的有意识的副作用,正如源代码评论所说,parent changed and it has precedence
......这意味着你的孤立范围的变化会失去
上面提到的$digest
方法通过仅更改第一个parentUpdate()
周期中隔离范围的值来避免此问题,该值允许将其成功复制到父范围,然后调用pkey
}
通常需要通过表达式将数据从隔离范围传递到父范围,这可以通过将局部变量名称和值的映射传递到表达式包装器fn来完成。例如,如果表达式是increment(amount),那么我们可以通过将localFn称为localFn({amount:22})来指定金额值。
这意味着,在第2步,您可以通过以下对象地图传递parentUpdate({pkey: 'D+' + $scope.key })
的值:
{{1}}
这是更新的小提琴:http://jsfiddle.net/KbYcr/
答案 1 :(得分:0)
使用$scope.$apply()
代替$scope.$digest()
也可以。这也将触发rootScope上的摘要。