根据https://github.com/angular/angular.js/wiki/Understanding-Scopes,尝试数据绑定到附加到$scope
的基元是一个问题:
范围继承通常很简单,你甚至不需要知道它正在发生......直到你尝试双向数据绑定(即表单元素,ng-model)到一个原语(例如,数字) ,string,boolean)在子范围内从父范围定义。它不像大多数人预期的那样有效。
建议
通过遵循始终拥有'。'的“最佳实践”,可以轻松避免使用原语这个问题。在您的ng模型中
现在,我有这个非常简单的设置违反了这些规则:
HTML:
<input type="text" ng-model="theText" />
<button ng-disabled="shouldDisable()">Button</button>
JS:
function MyController($scope) {
$scope.theText = "";
$scope.shouldDisable = function () {
return $scope.theText.length >= 2;
};
}
这真的很糟糕吗?当我开始尝试使用子范围时,这会以某种可怕的方式让我搞砸了吗?
我是否需要将其更改为
function MyController($scope) {
$scope.theText = { value: "" };
$scope.shouldDisable = function () {
return $scope.theText.value.length >= 2;
};
}
和
<input type="text" ng-model="theText.value" />
<button ng-disabled="shouldDisable()">Button</button>
让我遵循最佳做法?你可以给我一个具体的例子,后者会让我免受前者可能产生的一些可怕后果的影响吗?
答案 0 :(得分:19)
lot 的东西引入了新的范围。让我们说在你的控制器中,你实际上想要添加标签:第一个标签是实际渲染,第二个标签是表格(这样你就可以实时预览)。
您决定使用指令:
<tabs>
<tab name="view">
<pre>{{theText|formatInSomeWay}}</pre>
</tab>
<tab name="edit" focus="true">
<input type="text" ng-model="theText" />
</tab>
</tabs>
嗯,知道吗? <tabs>
有自己的范围,打破了你的控制器!因此,在编辑时,angular将在js中执行类似的操作:
$scope.theText = element.val();
不会遍历原型链,试图在父母身上设置theText
。
所以:现在可能不需要 ,因为您在该视图中还没有子范围,但您不知道是否要添加子模板或不是,最终可能会自行修改theText
,导致问题。为了将来证明你的设计,请始终遵循规则,然后你就不会感到惊讶了。)。
答案 1 :(得分:5)
假设您有范围M,A和B,其中M是A和B的父级。
如果(A,B)中的一个尝试写入M的范围,它将仅适用于非原始类型。原因是非原始类型通过引用传递。
另一方面,原始类型不是,因此尝试在M的作用域上写入theText
将分别在A或B的作用域上创建一个同名的新属性,而不是写入M. A和B都依赖于这个属性,会发生错误,因为他们中的任何一个都不知道另一个人正在做什么。