在Angular中,为什么要始终在$ scope中使用对象?

时间:2014-03-28 16:42:15

标签: angularjs

我在不同的地方读到,你总是在你的范围内使用对象是很重要的,但我还没有找到关于它为什么会有明确答案的答案。有人可以帮助我吗?

4 个答案:

答案 0 :(得分:5)

我喜欢Ryan Q的答案,但在做了一些更多的研究后,我想添加一个更加强调javascript原型继承的答案。

这里的问题是对象与原始问题(通过引用传递和按值传递)以及Javascript的原型继承如何工作。

当javascript类继承自父类时,它会将值复制到子类中。可以复制两种类型的值,对象或基元。

通过继承复制对象时,它通过引用传递。这意味着我在子对象中进行的任何更新也将在父对象中看到。

通过继承复制原语时,它将按值传递。这意味着在父类中不会看到任何更新。

这与Angular范围有什么关系?当我们创建一个指令时,将为该指令创建一个作用域,我们可以将它声明为一个孤立的作用域或一个继承的作用域。如果它是继承的范围,它将继承其父级的范围项。现在,如果我在父作用域中有原始值,我会将它们作为pass by value继承到我的子作用域中。这意味着当我在父作用域中进行更改时,在我的子作用域中不会看到它,反之亦然。现在我可以在我的子和父范围中使用不同的值具有相同的继承变量。这会导致混乱......可能是愤怒......哈哈。

因此,如果您只使用一个对象,那么这个问题就不会发生。这就是为什么你应该总是在范围内对象。

答案 1 :(得分:1)

答案 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;在父范围内。

相关问题