【问题标题】:If you are not using a .(dot) in your AngularJS models you are doing it wrong?如果你没有在你的 AngularJS 模型中使用 .(dot) 你做错了吗?
【发布时间】:2013-08-10 07:14:15
【问题描述】:

我记得在 AngularJS 的视频中看到这句名言说应该始终使用 . (点)在您的模型中。

好吧,我正在尝试按照这个说我有

   var item = {}
   item.title = "Easy Access to support";
   item.available = true;
   item.price = 31.67;

所以我认为这很有效

  {{ item.title }}
  {{ item.available }}

我使用的是点,所以我认为这很好。

但是我有一些属性我不认为是模型的一部分,但也许我错了。例如,我有一个使用 ng-disable 启用或禁用按钮的属性,我使用点格式输入了这个属性。它基本上是这样输入的

 $scope.disableButton = true;

我像使用它一样使用它

 ng-disable="disableButton"......

我应该将模型的这一部分设为“项目”吗?或者创建另一个 js 对象,这样我就可以使用点来保存这个属性?

有人知道这是否可以接受,还是我应该用 .dot 做所有事情(甚至是这些简单的属性)??

谢谢

【问题讨论】:

  • 这是视频中 Miško 提到您需要使用 ng-model 的“点”的确切位置:youtube.com/…
  • “使用点”分崩离析的一个地方是,如果您的指令采用 ngModel 但包装了其他指令并将 ngModel 传递给其他指令。一旦第一次通过,点符号就会丢失,因为变量在传递给第一个指令后立即重命名为“ngModel”(或您设置的任何别名)。从那时起,它被称为“ngModel”,它没有点符号并被视为一个原语,这会影响它在嵌套指令链中进一步向下传递的能力

标签: angularjs angularjs-scope


【解决方案1】:

这是需要点的情况。

当您有一个 $scope 值要用作 ngModel 值(我们称之为 selectedItem)时,您可能会想创建 $scope.selectedItem 并将其传递给模板。但是,如果模板创建子作用域,这很危险

有些 AngularJS 指令会创建子作用域:

  • ngRepeat
  • ngIf
  • ngController
  • ...和其他人(他们的doc page 会在“使用”标题下说“此指令创建新范围”)。

由于作用域继承的工作原理,子作用域很危险。关系是这样的:

-- $parent scope
   ├ selectedItem
   └─ $child scope

作为子作用域,$child 对象原型继承$parent。这是一个 JavaScript 术语,基本上意味着您可以通过获取$child.<property>获取任何$parent 属性。但是您不能设置 值,这就是问题所在。这就是 javascript 的工作原理。

所以模板可以通过读取$child.selectedItem访问$parent.selectedItem。但是如果模板设置$child.selectedItem,它设置在$child而不是$parent,所以现在你有两个版本的selectedItem

-- $parent scope
   ├ selectedItem
   └─ $child scope
      └ selectedItem

ngModel 指令getset 范围值。获取工作,但设置破坏了事情(ss其他人已经解释)。

为什么使用点可以解决问题

当您在父作用域上存储带有点的selectedItem 值时(例如$scope.vm.selectedItem,那么子作用域模板只会获取vm 对象。

使用vm,关系如下:

-- $parent scope
   ├ selectedItem
   │ └─ vm
   │     └─ selectedItem
   └─ $child scope

$child 作用域只读取 vm 对象;它从不写入一个新的 vm 对象(在 JS 中,对象是引用而不是值)。而原型继承只涉及访问vm。在作用域获得vm 对象后,它可以直接使用其值而无需任何原型继承。

把它想象成在作用域之间传递一个对象。

【讨论】:

    【解决方案2】:

    “你的模型中应该总是有一个点”是指ngModel。该指令执行双向绑定。如果你双向绑定到一个原语(例如你的情况下的布尔值),setter 会将它设置在当前范围而不是定义它的范围上,当你有一个大用户时,这可能会导致头痛 -与许多子范围的接口。 它没有引用其他指令,例如ngDisable有关此特定问题的更多详细信息,请参阅this explanation

    示例场景:父作用域为$scope.foo = "bar",子作用域为<input type="text" data-ng-model="foo">。它最初会显示bar,但是一旦用户更改了值,就会在子范围上创建foo,并且绑定将读取和写入该值。父级的foo 将保持为bar。希望总结的好。

    因此,对于ngModel 而言,您可能必须创建一个对象来解决此类绑定问题,但对于任何其他指令,您应该具有常规的逻辑分组。

    【讨论】:

    • 'controllerAs' 语法非常适合此目的(并且通常可以避免范围混淆)。
    • 我见过的最清晰、最简洁的解释。
    • 很好的解释!谢谢。
    • 但是为什么呢?为什么foo 不会在子范围内创建而something.foo 没有?
    • 这是由于在 JavaScript 中访问对象属性的方式。简单地说,在 JavaScript 中,$scope.foo = "bar" 表示“将对象 $scope 的属性 foo 设置为值“bar”。$scope.foo.bar = "baz" 表示“将对象 $scope 的对象 foo 的属性 bar 设置为“baz”。这里的重要区别在第一个示例中,foo 是要设置的属性,而在第二个示例中,foo 是要获取的对象。设置永远不会上原型链,如果没有找到,获取可以上原型链。同样的事情也适用于ngModel,其值为foofoo.bar。希望这会有所帮助。
    猜你喜欢
    • 1970-01-01
    • 2011-12-02
    • 1970-01-01
    • 1970-01-01
    • 2011-05-30
    • 2011-04-15
    • 2014-06-03
    • 2011-11-08
    相关资源
    最近更新 更多