我在这样的指令中绑定变量:
<path-filter-modal is-opened="filterModalIsOpened">
在指令中我使用'='绑定如下:
scope: {
isOpened: '='
}
当我在指令中更改变量时,父作用域包含自己的值。 如何使父范围包含相同的值?
对于对象,它运行良好,但不使用字符串和布尔值。 请注意,我在我的指令中使用我的指令中定义的控制器来更改值。
答案 0 :(得分:1)
因为JavaScript的设计是这样的。
在指令中定义隔离范围会创建一个新的$scope
对象,该对象是一个单独的$scope
对象。它与父范围的唯一关系是:$isolateScope.$parent === $parentScope
。 它不会继承$parentScope
原型。
当您为$scope.isOpened
分配一些基本类型(字符串/布尔值)时,实际上JavaScript引擎会在isOpened
上创建新变量$scope
。它与$parentScope.isOpened
完全无关。
但是现在,Angular会隐式地同步这两个变量。所以绑定原始变量仍然使two-way binding
运行良好。请检查JSFiddle。
如果绑定到某个对象类型,则子范围和父范围将引用内存中对象的完全相同副本。更改父作用域将自动更改子作用域。因此,始终建议two-way binding
绑定对象,而不是基本类型。
检查JSFiddle。我将一个原语和一个对象绑定到指令myDirective
。然后在link
函数中修改它们:
scope.primitiveParam = 'primitive from directive';
// $parent.primitive and primitiveParam refer to different memory;
// Angular is responsible to sync them.
console.log(scope.$parent.primitive);
console.log(scope.primitiveParam);
scope.objectParam.name = 'object from directive';
// $parent.obj and objectParam refer to an identical object
console.log(scope.$parent.obj.name);
console.log(scope.objectParam.name);
console.log(scope.objectParam === scope.$parent.obj);
结果如下:
primitive from parent
primitive from directive
object from directive
object from directive
详细信息:Understanding Scopes(这里有许多直观的图片,清楚地说明了这些概念)
答案 1 :(得分:1)
RE:对于对象,它运行良好,但没有字符串和布尔值
我认为这是原型继承问题的常见情况。当模型来自对象时,它运行良好,但如果它来自非对象,那么可能会在子范围内创建ng模型。
要解决该问题,请使用现代方法,使用Controller as
方法。或者将filterModelIsOpened放在一个对象中。第一种方法更好。
<div ng-controller="SomeController as s">
<path-filter-modal is-opened="s.filterModalIsOpened">
</div>
function SomeController() { // no need to use $scope
this.filterModalIsOpened = false;
}
或者如果您使用的是旧版Angular,则无法使用Controller as
方法。只需在控制器中创建自己的别名:
<div ng-controller="SomeController">
<path-filter-modal is-opened="s.filterModalIsOpened">
</div>
function SomeController($scope) {
$scope["s"] = this;
this.filterModalIsOpened = false;
}
这是一篇解释原型继承的好文章:http://codetunnel.io/angularjs-controller-as-or-scope/
以下是演示为什么 总是 为模型添加前缀的原因,无论它们是对象还是原始的。
不推荐。实时代码演示:http://jsfiddle.net/hdks813z/1/
<div ng-app="App" ng-controller="Ctrl">
<div ng-if="true">
<input type="checkbox" ng-model="filterModalCanBeOpened"/>
<the-directive primitive-param="filterModalCanBeOpened"></the-directive>
</div>
<hr/>
<p>
The value below doesn't react to changes in primitive(non-object) property
that is created a copy on a directive(e.g., ng-repeat, ng-if) that creates
child scope
</p>
$scope.primitive: {{filterModalCanBeOpened}}
</div>
angular.module('App', [])
.directive('theDirective', function () {
return {
restrict: 'AE',
scope: {
primitiveParam: '='
},
template: '<div>primitiveParam from directive: {{ primitiveParam }}; </div>',
link: function (scope) {
}
};
})
.controller('Ctrl', ['$scope', function ($scope) {
$scope.filterModalCanBeOpened = true;
}]);
推荐:实时代码演示:http://jsfiddle.net/2rpv27kt/
<div ng-app="App" ng-controller="Ctrl as c">
<div ng-if="true">
<input type="checkbox" ng-model="c.filterModalCanBeOpened"/>
<the-directive primitive-param="c.filterModalCanBeOpened"></the-directive>
</div>
<hr/>
<p>
The value below react to changes in primitive(non-object) property that is
addressed directly by its alias c, creating child scope on it would be
impossible. So the primitive below react to changes on
the c's filterModalCanBeOpened.
</p>
c.primitive: {{c.filterModalCanBeOpened}}
</div>
angular.module('App', [])
.directive('theDirective', function () {
return {
restrict: 'AE',
scope: {
primitiveParam: '='
},
template: '<div>primitiveParam from directive: {{ primitiveParam }}; </div>',
link: function (scope) {
}
};
})
.controller('Ctrl', [function () {
this.filterModalCanBeOpened = true;
}]);