【发布时间】:2014-06-07 11:47:00
【问题描述】:
这里的提琴手:http://jsfiddle.net/u9PLF/
我得到了一个有嵌套孩子的父母名单。我会定期更新整个对象层次结构并更新第一个父级的子级数组一次。我遇到的问题是,children 数组似乎总是在更新,或者至少每次我调用 fromJS 函数时它都会通知订阅者。
我希望子 observableArray 只通知订阅者一次(当它第一次从 [A,B] 更改为 [A,B,C] 时,而不是在随后的调用中)。
我做错了什么?
谢谢
代码:
var data = {
parents: [{
id: 1,
name: 'Scot',
children: ['A', 'B']
}]
};
function ParentVM(data) {
var self = this;
ko.mapping.fromJS(data, {}, self);
self.count = ko.observable(0);
self.hello = ko.computed(function () {
console.log("Update", self.children());
self.count(self.count() + 1);
});
}
var mapping = {
parents: {
create: function (options) {
return new ParentVM(options.data);
},
key: function (data) {
return ko.utils.unwrapObservable(data.id);
}
}
};
var viewModel = ko.mapping.fromJS(data, mapping);
ko.applyBindings(viewModel);
setInterval(function () {
var data = {
parents: [{
id: 1,
name: 'Scott',
children: ['A', 'B', 'C']
}]
};
ko.mapping.fromJS(data, mapping, viewModel);
}, 2000);
viewModel.parents.subscribe(function () {
console.log("Parents notif");
});
【问题讨论】:
-
我对映射插件不是很熟悉,所以它可能足够聪明来处理这个问题,但我猜这与
['A','B','C'] != ['A','B','C']在 javascript 中的事实有关。所以天真的“这个值变了吗?”函数会认为它已经改变了。 -
我很难过,也许忽略了一些东西,但如果你只是注释掉子部分,你会注意到完全相同的行为,而只有一个
id和name父母(“父母通知”)不断在控制台中弹出。第一次当然是正确的,将名称从 Scot 更改为 Scott,但应通过key:´ part inmapping` 阻止任何后续更改。 -
@MajorByte,我没有阅读 ko.mapping 源代码,但我的猜测是 ko.mapping 不知道 parents[0] 的内容永远不会改变。它在
name('Scott')上调用了update,即使name没有触发更改事件,ko.mapping 也必须盲目地广播parents的更改事件,因为它在下面的字段中执行了一些操作。 -
@huocp,似乎是这样,但仍然让我觉得很奇怪。因为
parents没有改变,第一次setInterval回调执行后children也没有改变,children数组中的任何字段也没有,所以为什么需要发送一个事件数组发生了变化,但绝对没有任何变化。 -
@MajorByte,来自 ko.mapping 源代码第 590-634 行,当 mappedRootObject 是一个数组(如父母)时,它会遍历数组中的所有项目,然后调用
mappedRootObject(newContents)而不检查newContents 的内容是否与现有内容不同。我认为这条 634 行会为父母触发更改事件。这是一个不太好的证明:jsfiddle.net/zDa3K/4 带有自定义的 ko.mapping 源代码打印在第 634 行之前和之后。
标签: javascript knockout.js knockout-mapping-plugin ko.observablearray