【问题标题】:In Angular, why should you always use objects in the your $scope?在 Angular 中,为什么要始终在 $scope 中使用对象?
【发布时间】:2014-03-28 16:42:15
【问题描述】:

我在不同的地方读到过,始终使用范围内的对象很重要,但我还没有找到明确的答案来解释为什么会这样。有人可以帮帮我吗?

【问题讨论】:

  • Cherniv:我认为您所链接的答案确实为这个问题提供了指导,并且深入探讨了更大范围的问题。但我相信这个页面上的问题讨论了 Angular 开发人员应该知道的一个重要且更具体的问题。因此,我相信它有必要做出自己的回应。

标签: angularjs


【解决方案1】:

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

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

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

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

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

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

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

【讨论】:

    【解决方案2】:
    【解决方案3】:

    假设您有 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 评估 "helloWorld = false" 时,它会在内部设置 $scope["helloWorld"] = 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 在 Sub1Ctrl 上评估“myModel.helloWorld”,最终在父 MainCtrl 上找到“myModel”,因此正确地将 helloWorld 属性设置为 false。

    【讨论】:

      【解决方案4】:

      因为您将数据保存在一个地方。例如,子范围(不是孤立范围)可以隐藏属性“消息”。所以父作用域和子作用域都有一个“消息”属性。但是如果父作用域有“data.message”属性,子作用域不能遮蔽它,除非首先在子作用域中创建一个属性“data”,然后是“data.message”,但这不是AngularJS所做的。但 AngularJS 确实在父范围内创建了第一个“数据”,然后创建了“data.message”。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-12-10
        • 2017-05-18
        • 1970-01-01
        相关资源
        最近更新 更多