我在不同的地方读到,你总是在你的范围内使用对象是很重要的,但我还没有找到关于它为什么会有明确答案的答案。有人可以帮助我吗?
答案 0 :(得分:5)
我喜欢Ryan Q的答案,但在做了一些更多的研究后,我想添加一个更加强调javascript原型继承的答案。
这里的问题是对象与原始问题(通过引用传递和按值传递)以及Javascript的原型继承如何工作。
当javascript类继承自父类时,它会将值复制到子类中。可以复制两种类型的值,对象或基元。
通过继承复制对象时,它通过引用传递。这意味着我在子对象中进行的任何更新也将在父对象中看到。
通过继承复制原语时,它将按值传递。这意味着在父类中不会看到任何更新。
这与Angular范围有什么关系?当我们创建一个指令时,将为该指令创建一个作用域,我们可以将它声明为一个孤立的作用域或一个继承的作用域。如果它是继承的范围,它将继承其父级的范围项。现在,如果我在父作用域中有原始值,我会将它们作为pass by value继承到我的子作用域中。这意味着当我在父作用域中进行更改时,在我的子作用域中不会看到它,反之亦然。现在我可以在我的子和父范围中使用不同的值具有相同的继承变量。这会导致混乱......可能是愤怒......哈哈。
因此,如果您只使用一个对象,那么这个问题就不会发生。这就是为什么你应该总是在范围内对象。
答案 1 :(得分:1)
看看这个: https://github.com/angular/angular.js/wiki/Understanding-Scopes 和 Does my ng-model really need to have a dot to avoid child $scope problems?
答案 2 :(得分:1)
假设您有3个控制器,一个主控制器和另外两个从主控制器继承的控制器。
你的HTML可能看起来像这样。
<div ng-controller="MainCtrl">
<div ng-show="helloWorld">Hello World</div>
<div ng-controller="Sub1Ctrl">
<button type="button" ng-click="helloWorld = false">Hide Hello World</button>
</div>
<div ng-controller="Sub2Ctrl">
<button type="button" ng-click="helloWorld = false">Hide Hello World</button>
</div>
</div>
您的主控制器
angular.module('MyModule').controller('MainCtrl', function( $scope ){
$scope.helloWorld = true;
});
一切都很好,花花公子,你的hello world元素按预期显示。现在尝试单击其中一个将helloWorld设置为false的按钮。你的Sub1Ctrl现在看起来像这样:
angular.module('MyModule').controller('Sub1Ctrl', function( $scope ){
$scope.helloWorld = false;
});
但你的MainCtrl仍然是
angular.module('MyModule').controller('MainCtrl', function( $scope ){
$scope.helloWorld = true;
});
为什么?好吧,因为当Angular评估&#34; helloWorld = false&#34;它在内部设置$ scope [&#34; helloWorld&#34;] = false。问题是因为您将其设置在较低的Sub1Ctrl上,从不设置较高的控制器。
如果您将Html和MainCtrl更改为:
<div ng-controller="MainCtrl">
<div ng-show="myModel.helloWorld">Hello World</div>
<div ng-controller="Sub1Ctrl">
<button type="button" ng-click="myModel.helloWorld = false">Hide Hello World</button>
</div>
<div ng-controller="Sub2Ctrl">
<button type="button" ng-click="myModel.helloWorld = false">Hide Hello World</button>
</div>
</div>
angular.module('MyModule').controller('MainCtrl', function( $scope ){
$scope.myModel = {
helloWorld: true
}
});
然后Angular会在设置值之前查看对象是否存在于范围原型中(这是控制器通过Scope Hierarchy继承的方式)。
所以现在Angular评估&#34; myModel.helloWorld&#34;在Sub1Ctrl上最终找到&#34; myModel&#34;在父MainCtrl上,所以正确地将helloWorld属性设置为false。
答案 3 :(得分:0)
因为那时你将数据保存在一个地方。子范围(不是孤立的范围)可以隐藏属性&#34;消息&#34;例如。因此,父范围和子范围有一个&#34;消息&#34;属性。但是如果父范围有&#34; data.message&#34;属性,子范围不能影这个,除非先是属性&#34;数据&#34;在子范围中创建,然后是&#34; data.message&#34;,但这不是AngularJS的功能。但AngularJS确实创造了第一个数据&#34;然后&#34; data.message&#34;在父范围内。