Javascript AngularJS:指令中未更新父作用域(使用隔离作用域)双向绑定
我有下面的代码,也可以修改 视图:Javascript AngularJS:指令中未更新父作用域(使用隔离作用域)双向绑定,javascript,angularjs,scope,directive,two-way,Javascript,Angularjs,Scope,Directive,Two Way,我有下面的代码,也可以修改 视图: {{pkey}} JS: var testApp=angular.module('testApp',[]); testApp.directive('testDirective',函数($timeout){ 返回{ 范围:{ 键:'=parentItem', parentUpdate:“&” }, 替换:正确, 模板:'{{key}}'+ “锁”+ '', 控制器:函数($scope、$element、$attrs){ $scope.lock=函数(){ $
{{pkey}}
JS:
var testApp=angular.module('testApp',[]);
testApp.directive('testDirective',函数($timeout){
返回{
范围:{
键:'=parentItem',
parentUpdate:“&”
},
替换:正确,
模板:'{{key}}'+
“锁”+
'',
控制器:函数($scope、$element、$attrs){
$scope.lock=函数(){
$scope.key='D++$scope.key;
log('DIR:',$scope.key);
//预期$scope.$parent.pkey也已被删除
//在调用下一行之前更新。
$scope.parentUpdate();
//$timeout($scope.parentUpdate);//可以工作。
};
}
};
});
testApp.controller('testCtrl',函数($scope){
$scope.pkey='golden';
$scope.update=函数(k){
//应使用局部变量k或$scope.pkey
//由指令范围内的调用更新。
log('CTRL:',$scope.pkey,k);
$scope.pkey='C+'+k;
log('CTRL:',$scope.pkey);
};
});
基本上,我用一个独立的作用域设置指令,在这个指令中,我从父作用域(pkey)双向绑定一个属性(键),并且还委托一个方法(parentUpdate)在父作用域的上下文中调用
现在,在指令中的ng click事件处理程序中,我想调用parentUpdate方法并在其中执行一些操作。当我调用该方法时,我希望父作用域的模型已经更新。但事实并非如此,这正是让我困惑的地方
这可能是因为中间有一些丢失的摘要周期,因为用$TimeOutin包装PalpUpUPDATE调用会正常工作。
有人能解释一下遗漏了什么吗?或者如何正确调用parentUpdate?好的,我将尝试一下这个。。。在双向逻辑同步两个变量的
$digest
循环之前,您似乎正在更改独立的子变量和父变量。详情如下:
lock()
函数。这将更新隔离的$scope.key
变量注意:这不会立即更新父级$scope.pKey
;这通常会在下一个$digest
周期发生,但在本例中不会发生。继续阅读…lock()
中,您正在调用parentUpdate()
,它更新父级的$scope.pKey
变量$digest
循环。当它循环到父作用域时,将正确检测到对$scope.pKey
的更改$scope.pKey的更改将触发由隔离作用域中的双向绑定创建的watch()
。是最关键的
watch()
检查双向绑定的值是否与父绑定的值同步。如果不是(在本场景中也不是),则将父级的值复制到隔离作用域,即使隔离作用域的值也已更改,并且实际上是先更改的$digest
循环方法的优点。您在这里看到的是$digest
改变coalesence方法的一个有意识的副作用,正如源代码注释所说。。。这意味着您的独立作用域的更改将丢失
上面提到的$timeout()
方法通过在第一个$digest
循环中仅更改隔离作用域的值来避免此问题,该循环允许将其成功复制到父作用域,然后调用parentUpdate()
报告说:
通常需要通过表达式将数据从隔离范围传递到父范围,这可以通过将局部变量名和值的映射传递到表达式包装器fn来完成。例如,如果表达式是increment(amount),那么我们可以通过调用localFn作为localFn({amount:22})来指定amount值
这意味着,在步骤#2,您可以通过如下对象映射传入pkey
的值:
parentUpdate({pkey: 'D+' + $scope.key })
下面是更新后的提琴:使用
$scope.$apply()
而不是$scope.$digest()
也可以使用。这也将触发rootScope上的摘要。好的,所以这里有一点目标。。。您想知道为什么$scope.key='D++$scope.keylock()
函数中的code>似乎没有任何效果,对吧?感谢您的解释,它真的很有帮助!虽然我知道这是由于$digest循环的设计。我正在寻找一种方法,使隔离作用域的属性构建在父作用域的属性之上,而不必调用超时函数。在这种情况下,由于我们已经处于摘要周期中,我们不能再调用$digest或$apply。理想情况下,我希望调用evalAsync,但这似乎也不起作用。如果angular的袖子中有一个技巧可以绕过这种设计,那将是非常棒的。我认为这就是这样一个技巧:-)我刚刚用细节更新了我的答案,并使用了一个新的JSFIDLE,其中有一个小小的更改来演示它。
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);
};
});
parentUpdate({pkey: 'D+' + $scope.key })