使用ng-model、ng-repeat和inputs时遇到的困难。
使用ng-model、ng-repeat和inputs时遇到的困难。
我尝试使用ngRepeat
和ngModel
来允许用户编辑一个项目列表(请参见这个fiddle)。然而,我尝试的两种方法都导致了奇怪的行为:其中一种不更新模型,另一种在每个键按下时都使表单失去焦点。我在这里做错了什么吗?这不是一个支持的用例吗?以下是从fiddle中复制的代码,为了方便起见:
Fun with Fields and ngModel
names: {{names}}Binding to each element directly:
Value: {{name}}绑定似乎没有起作用:模型中的值没有改变。
Indexing into the array:
Value: {{names[$index]}}输入一个字符,输入框就会失去焦点。然而,绑定似乎工作正常。
问题出现的原因是在使用ng-model、ng-repeat和inputs时,对于作用域、ngRepeat和ngModel与NgModelController的工作原理不够了解。在1.0.3版本中,示例的运行方式会有一些不同。
解决方法如下:
- 可以简单地使用jm-提供的解决方案。
- 如果想更深入地处理这种情况,必须理解以下内容:
- AngularJS的工作原理;
- 作用域具有层次结构;
- ngRepeat为每个元素创建一个新的作用域;
- ngRepeat使用附加信息(hashKey)构建项目的缓存;在每次新项目(不在缓存中)的监视调用时,ngRepeat构建新的作用域、DOM元素等。更详细的描述请参考链接。
- 从1.0.3版本开始,ngModelController使用实际模型值重新渲染输入。
在AngularJS 1.0.3中,“直接绑定到每个元素”示例的工作原理如下:
- 在输入框中输入字母'f';
- ngModelController更改项目作用域的模型(names数组不变)=> name == 'Samf',names == ['Sam', 'Harry', 'Sally'];
- 启动$digest循环;
- ngRepeat将项目作用域中的模型值('Samf')替换为未更改的names数组中的值('Sam');
- ngModelController使用实际模型值('Sam')重新渲染输入框。
“索引到数组”示例的工作原理如下:
- 在输入框中输入字母'f';
- ngModelController更改names数组中的项目=> names == ['Samf', 'Harry', 'Sally'];
- 启动$digest循环;
- ngRepeat在缓存中找不到'Samf';
- ngRepeat创建新的作用域,添加带有新输入框的新div元素(这就是为什么输入框会失去焦点-旧的div和旧的输入框被新的div和新的输入框替换);
- 渲染新的DOM元素的新值。
此外,您可以尝试使用AngularJS Batarang工具,查看您输入的输入框所在的作用域的$id如何更改。
感谢对1.0.3版本的解释。有趣的是,在1.0.3版本中,“直接绑定”示例中,输入框似乎是损坏的,因为它似乎无法接受任何更改/输入(至少在Chrome中是如此)。我相信我们会在不久的将来看到很多关于这个问题的Stack Overflow帖子 🙂 我认为这种新的方式更好,因为它会更明显地显示出问题所在。