gpt4 book ai didi

javascript - knockout 映射 > 映射数组始终更新

转载 作者:塔克拉玛干 更新时间:2023-11-02 21:01:24 25 4
gpt4 key购买 nike

fiddler 在这里:http://jsfiddle.net/u9PLF/

我得到了一个有嵌套子项的 parent 列表。我定期更新整个对象层次结构并更新一次第一个父项的子项数组。我遇到的问题是 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");
});

最佳答案

@Charlie 是对的。这与 ko.mapping 无关,这是 ko.observable 测试值相等性的方式。

http://jsfiddle.net/C7wUb/

在此演示中,每次调用 items([1,2]) 时都会更新项目

var vm = {
items: ko.observable([1,2]),
count: ko.observable(0)
};

vm.items.subscribe(function(new_v) {
console.log("items are updated to " + new_v);
vm.count(vm.count() + 1);
});

ko.applyBindings(vm);

setInterval(function() {
vm.items([1,2]);
}, 2000);

更深层次的原因是ko的equalityComparer的默认实现,它只比较原始类型。

// src/subscribables/observable.js
ko.observable['fn'] = {
"equalityComparer": valuesArePrimitiveAndEqual
};

// src/subscribables/extenders.js
var primitiveTypes = { 'undefined':1, 'boolean':1, 'number':1, 'string':1 };
function valuesArePrimitiveAndEqual(a, b) {
var oldValueIsPrimitive = (a === null) || (typeof(a) in primitiveTypes);
return oldValueIsPrimitive ? (a === b) : false;
}

避免在 observableArray 上发生不必要的更新事件的方法是覆盖 equalityComparer。

http://jsfiddle.net/u9PLF/2/

var oldComparer = ko.observable.fn.equalityComparer;

ko.observable.fn.equalityComparer = function(a, b) {
var i, toStr = Object.prototype.toString;
if (toStr.call(a) === '[object Array]' && toStr.call(b) === '[object Array]') {
if (a.length !== b.length) return false;
for (i = 0; i < a.length; i++) {
if (!oldComparer(a[i], b[i])) return false;
}
return true;
} else {
return oldComparer(a, b);
}
};

(你也可以只为子observableArray覆盖equalityComparer,看看ko.extenders notify是如何在src/subscribables/extenders.js中实现的)

顺便说一句,您执行 self.hello = ko.computed(...) 的方式有点冒险。

self.hello = ko.computed(function () {
console.log("Update", self.children()); // you want to notify self.hello when children change.
self.count(self.count() + 1); // but self.hello also has dependency on self.count()
});

我想你想要的是一个简单的subscribe,为children change事件注册一个回调。

self.children.subscribe(function(new_v) {
console.log("Update", new_v);
self.count(self.count() + 1);
});

关于javascript - knockout 映射 > 映射数组始终更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23230826/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com