视图:
<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方法并在其中执行某些操作.当我调用该方法时,我期望我的父范围的模型被更新.但实际上,这不是,这是令我困惑的.
这可能是因为中间的一些缺少$摘要循环,因为用$timeout包装parentUpdate调用将按预期工作.
有人会说出一些缺点吗?还是如何正确调用parentUpdate?
解决方法
首先通过点击按钮执行你的lock()函数.这将更新隔离的$scope.key变量.注意:这不会立即更新父$scope.pKey;通常会在下一个$摘要循环中发生,但在这种情况下不会.阅读…
>在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()
Often it’s desirable to pass data from the isolated scope via an expression and to the parent scope,this can be done by passing a map of local variable names and values into the expression wrapper fn. For example,if the expression is increment(amount) then we can specify the amount value by calling the localFn as localFn({amount: 22}).
这意味着,在步骤2中,您可以通过像这样的对象映射传递您的pkey值:
parentUpdate({pkey: 'D+' + $scope.key })
这是更新的小提琴:http://jsfiddle.net/KbYcr/