以下a jsFiddle证明了以下问题:
给定一个(可观察的)字符串列表的foreach绑定,observable似乎不会更新为foreach中绑定的输入标记的更改。人们会期待他们。这是jsFiddle的例子:
<ul data-bind='foreach: list'>
<li><input data-bind='value: $data'/></li>
</ul>
<ul data-bind='foreach: list'>
<li><span data-bind='text: $data'></span></li>
</ul>
var vm = { list: [ko.observable('123'), ko.observable('456')] };
ko.applyBindings(vm);
在上面的示例中,可以预期更新第一个列表中的输入标记会导致observable更新。不幸的是,它们没有按预期更新,因为第二个列表未能反映对第一个列表所做的任何更改。
我确认在更改输入元素时实际上没有更新列表。
有趣的是,对可观察量的改变反映在两个列表中(正如人们所预料的那样)。即,vm.list[1]("444")
将更新两个列表的第二个元素。
我的回忆是Knockout 2.0.0没有这个问题,尽管我有待纠正。我没有在Knockout代码中找到任何文档,Google或评论,这些代码产生了为什么这不起作用或如何达到预期结果的任何迹象。
为什么这不能按预期工作,是否有任何不需要更改数据结构的变通方法?
答案 0 :(得分:15)
我使用value: $parent.list[$index()]
解决了这个问题,如this jsFiddle所示。新绑定看起来像这样:
<ul data-bind='foreach: list'>
<li>
<input data-bind='value: $parent.list[$index()]' />
</li>
</ul>
可以通过自定义绑定来改进这一点。
另请参阅Knockout.js的相关GitHub issue #708。
Knockout 3.0的更新:
Knockout现在提供$rawData
:
<ul data-bind='foreach: list'>
<li><input data-bind='value: $rawData'/></li>
</ul>
按预期创建双向绑定。
来自 Binding Context 文档:
$ RAWDATA
这是当前上下文中的原始视图模型值。通常这个 将与$ data相同,但如果视图模型提供给Knockout 包含在一个可观察的数据中,$ data将是未包装的视图模型, 和$ rawData本身就是可观察的。
答案 1 :(得分:6)
默认敲除绑定中使用的每个数据对象将始终被解包。因此,您基本上绑定到列表中项目的值,而不是您期望的可观察值。
Observables应该是对象的属性,而不是对象本身的替代。将observable设置为某个对象的属性,这样就不会发生。
var vm = {
list: [
{ value: ko.observable('123') },
{ value: ko.observable('456') }
]
};
<ul data-bind='foreach: list'>
<li><input data-bind='value: value'/></li>
</ul>
<ul data-bind='foreach: list'>
<li><span data-bind='text: value'></span></li>
</ul>