为什么 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.name
与 name
时设置值有关。同样,这与原型继承的细微差别有关。
当ng-model
设置变量data.name
时,将写入继承data
object下的name
] 属性 - 正如预期的那样 - 在定义 data
的地方。换句话说,data
object 被读取(因此继承的 object 被读取)并且 name
属性 被写入。
然而,当 ng-model
设置变量 name
时,它将直接写入当前范围的 属性 name
,从而隐藏继承的 name
属性 来自 parent.
正确的做法是:
- 始终在
ng-model
(或任何 two-way 绑定属性)中使用点 (.) 符号。
根据您希望的位置定义 data
object - 不要让 ng-model
来定义。例如(如果这是意图),在 maincontroller
:
中定义它
.controller("maincontroller", function($scope){
$scope.data = {};
});
其效果是所有输入都将绑定到相同的 属性。
我在 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.name
与 name
时设置值有关。同样,这与原型继承的细微差别有关。
当ng-model
设置变量data.name
时,将写入继承data
object下的name
] 属性 - 正如预期的那样 - 在定义 data
的地方。换句话说,data
object 被读取(因此继承的 object 被读取)并且 name
属性 被写入。
然而,当 ng-model
设置变量 name
时,它将直接写入当前范围的 属性 name
,从而隐藏继承的 name
属性 来自 parent.
正确的做法是:
- 始终在
ng-model
(或任何 two-way 绑定属性)中使用点 (.) 符号。 根据您希望的位置定义
中定义它data
object - 不要让ng-model
来定义。例如(如果这是意图),在maincontroller
:.controller("maincontroller", function($scope){ $scope.data = {}; });
其效果是所有输入都将绑定到相同的 属性。