为什么 ng-model 在 angularjs 中表现异常?

why ng-model behave unexpectedly in angularjs?

我在 angular js 中举了两个例子,但我得到了意想不到的结果。 嵌套控制器的例子 :

第一个例子

<div ng-controller="maincontroller">
        <input ng-model="data.name">
         <h1>{{data.name}}</h1>

        <div ng-controller="nestedcontroller">
            <input ng-model="data.name">
             <h1>{{data.name}}</h1>

            <div ng-controller="nestedANOTHERcontroller">
                <input ng-model="data.name">
                 <h1>{{data.name}}</h1>

            </div>
        </div>
      <div ng-controller="nestedOUTERRcontroller">
                <input ng-model="data.name">
                 <h1>{{data.name}}</h1>

            </div>
    </div>

当我在所有嵌套控制器中使用 "data.name" 时。现在,当我更改任何输入字段时,它会反映在所有输入字段和 header 字段中。为什么?

其次 当我使用 "name" 而不是 "data.name"

 <div ng-controller="maincontroller">
            <input ng-model="name">
             <h1>{{name}}</h1>

            <div ng-controller="nestedcontroller">
                <input ng-model="name">
                 <h1>{{name}}</h1>

                <div ng-controller="nestedANOTHERcontroller">
                    <input ng-model="name">
                     <h1>{{name}}</h1>

                </div>
            </div>
          <div ng-controller="nestedOUTERRcontroller">
                    <input ng-model="name">
                     <h1>{{name}}</h1>

                </div>
        </div>

当我更改顶部输入字段时,它会在所有输入字段中更改,header field.but 当我移动到第二个输入字段时,它会更改为嵌套(children)输入字段和 header 但不更改为上层控制器和兄弟控制器,为什么?当我移动到最里面的控制器并更改输入字段内的文本时,它显示 header 。现在,如果 parent 控制器尝试更改其文本,它无法做到。parents 控制器现在只更改其文本,为什么?

这是我的代码 http://codepen.io/anon/pen/xGGJKR

谢谢

简短的回答是作用域属性的原型继承(不要将作用域用作模型,而是从作用域的某些 属性 创建对模型的引用)。通常使用服务或工厂或其他一些提供者定义来存储模型并完成大部分工作,并仅使用控制器使适当的提供者和数据可用于视图。

https://youtu.be/ZhfUv0spHCY?t=31m12s

What are the nuances of scope prototypal / prototypical inheritance in AngularJS?

这与作用域继承的工作原理有关。有关范围继承的细微差别的更全面的答案,请阅读此 SO answer

首先,您必须认识到 ng-controller 指令创建了一个 child 作用域,其原型继承自 parent,因此您在此处具有以下层次结构的嵌套作用域(数字是每个范围的 $id 个)

  #2
 /  \
#5  #3
      \
      #4

因此,当您在第一个 <input> 中键入内容时,它将在范围 #2 中创建 $scope.data = {name: "foo"} 并将被所有嵌套范围继承(可见)。另一方面,如果您输入第二个 <input> - 那么它将在 #3 范围内创建 $scope.data(如上),但 #2 和 [=21= 都不会] 将继承它。

第二点与使用 data.namename 时设置值有关。同样,这与原型继承的细微差别有关。

ng-model设置变量data.name时,将写入继承dataobject下的name ] 属性 - 正如预期的那样 - 在定义 data 的地方。换句话说,data object 被读取(因此继承的 object 被读取)并且 name 属性 被写入。

然而,当 ng-model 设置变量 name 时,它将直接写入当前范围的 属性 name,从而隐藏继承的 name 属性 来自 parent.

正确的做法是:

  1. 始终在 ng-model(或任何 two-way 绑定属性)中使用点 (.) 符号。
  2. 根据您希望的位置定义 data object - 不要让 ng-model 来定义。例如(如果这是意图),在 maincontroller:

    中定义它
    .controller("maincontroller", function($scope){
       $scope.data = {};
    });
    

    其效果是所有输入都将绑定到相同的 属性。