我准备了一把小提琴,并把它压缩到最低限度:
http://jsfiddle.net/lpeterse/NdhjD/4/
<script type="text/javascript">
angular.module('app', ['ui.bootstrap']);
function Ctrl($scope) {
$scope.foo = "42";
}
</script>
<div ng-app="app" ng-controller="Ctrl">
1: {{foo}}<br />
2: <input ng-model="foo" />
<tabs>
<pane heading="tab">
3: {{foo}}<br />
4: <input ng-model="foo" />
</pane>
</tabs>
</div>在开始时,所有视图都引用模型Ctrl.foo。
如果您在input 2:中更改了某些内容,它会正确地更新模型,并且此更改将传播到所有视图。
在input 4:中更改某些内容只会影响包含在同一窗格中的视图。它的行为就像作用域以某种方式派生出来的。之后,来自2:的更改将不再反映在选项卡中。
我阅读了有关指令、作用域和转换的angular文档,但找不到对这种不受欢迎的行为的解释。
如有提示,我将不胜感激:-)
发布于 2013-02-20 00:18:07
这个问题与编辑原语时在ng-repeat中的问题相同- <pane>指令创建了一个继承自父对象的新作用域。
现在,给定Javascript继承的工作方式,<pane>指令有它自己的foo字符串原语副本,当您编辑它时,您只能在窗格的子作用域上编辑它。
一个简单的解决方案是将foo放在父Ctrl上的一个对象中:
function Ctrl($scope) {
$scope.data = { foo: 42 };
}然后,您可以在HTML中执行以下操作:
<tabs><pane><input ng-model="data.foo"></pane></tabs>为什么它要与对象一起工作?因为当<pane>继承父对象的作用域时,它对data的引用将引用内存中与父Ctrl上相同的对象。像字符串和数字这样的原语是在继承中复制的,而对象只是创建一个指向同一对象的新指针。
<pane>的新作用域继承了foo字符串原语作为foo的新副本,当被编辑时不会在父Ctrl上改变。<pane>的新作用域将继承一个像data这样的对象作为对同一对象的引用,并且当在<pane>作用域上编辑时,相同的对象将在父作用域上被引用。
有用的文章:https://github.com/angular/angular.js/wiki/The-Nuances-of-Scope-Prototypal-Inheritance
发布于 2013-03-01 01:27:29
<tabs>和<pane>指令分别创建一个新的转换子作用域(因为它们都有transclude: true,)和一个隔离子作用域,前者通常从父作用域继承,后者不典型地从父作用域继承。<pane>中的<input...>使用被转换的子范围。
当第一次呈现<pane>中的input时,会用$scope.foo的值填充它。正常的JavaScript原型继承在这里开始发挥作用……最初,foo是在转换子作用域上定义的而不是(原型继承不复制原语),因此JavaScript遵循原型链并查看父对象/$ scope,并在那里找到它。将42放入文本框中。被转移的子作用域未受影响/更改(尚未)。
如果编辑第一个文本框,则会更新第二个文本框,因为JavaScript仍在使用原型继承来查找$scope.foo的值。
如果您编辑第二个文本框,也就是429,Angular会将值写入$scope.foo,但请注意,$scope是转换子范围。因为foo是一个原语,所以它在该子作用域上创建了一个新属性--无论好坏,这就是JavaScript的工作方式。此新属性将隐藏/隐藏同名的父作用域属性。原型继承在这里不起作用。(安迪在他的帖子(也是on SO)中提到的文章也详细解释了这一点,并附有图片。)由于转换子作用域现在具有foo属性,因此它现在将使用该本地属性进行读写,因此它看起来与父作用域“断开连接”。
使用对象(而不是原语)解决了这个问题,因为原型继承总是起作用的。转换子作用域获取对父作用域中的对象的引用。写入data.foo将写入父对象上的data对象,而不是被转换的子作用域。
发布于 2013-02-20 00:10:43
问题出在tabs指令中。我想是在line 1044 of ui-bootstrap-tpls-0.1.0.js上。
如果您将scope: {}更改为scope: { foo: '='},它将为您提供双向数据绑定。
来自Angular Docs
= or =attr -在本地作用域属性和通过attr属性的值定义的name的父作用域属性之间设置双向绑定。如果未指定attr名称,则假定属性名称与本地名称相同。给定和小部件范围的定义:{ localModel:'=myAttr‘},然后小部件范围属性localModel将反映父范围上的parentModel的值。对parentModel的任何更改都将反映在localModel中,而对localModel的任何更改都将反映在parentModel中。
https://stackoverflow.com/questions/14961155
复制相似问题