我是Knockout的新手,并且在单个页面上拥有多个组件实例时会苦苦挣扎。
背景。组件动态地从数据服务获取对象数组。根据用户操作,组件可能需要重新呈现数组(提供的新对象),因此数组是可观察的数组。
问题。页面上必须有多个组件实例,但它们必须独立工作。即使最初他们收到相同的对象数组。
我创建了一个简单的例子来说明问题。
HTML
Emulate data service call:
<button data-bind="click: getData">PULL</button><br>
Component 1:
<item-picker params="items: itemsArray"></item-picker>
Component 2:
<item-picker params="items: itemsArray"></item-picker>
的JavaScript。
ko.components.register("item-picker", {
viewModel: function(params) {
var self = this;
self.items = params.items;
self.addPerson = function() {
self.items.push({
name: "New at " + new Date()
});
};
},
template: "<button data-bind='click: addPerson'>Add</button><div data-bind='foreach: items'><p data-bind='text: name'></p></div>"
});
// top level viewmodel
var vm = function() {
var self = this;
self.itemsArray = ko.observableArray([]);
self.getData = function(){
self.itemsArray([]);
self.itemsArray.push({name: 'Bert'}, {name: 'Charles'}, {name: 'Denise'});
};
};
ko.applyBindings(new vm());
这个例子也可以在JSFiddle上找到:https://jsfiddle.net/ignas/14jgksj0/6/
修改 我应该提到数据服务调用是异步的,并且可以在页面加载之后接收数据,并且用户也能够强制重新检索数据(例如,使用不同的参数)。我相应地更新了代码片段和JSFiddle上的示例。
问题。在JSFiddle示例中,如何使组件独立工作? 即向“组件1”添加新名称不应将名称添加到“组件2”
答案 0 :(得分:0)
在构造函数中创建一个新的可观察数组包装器和内部数组:
self.items = ko.observableArray(params.items().slice(0));
https://jsfiddle.net/dx6b6nvy/
目前的结构中有两层:
observableArray
vm.itemsArray
个实例
目前,所有组件都通过(1)修改(2)。为了确保每个组件都有自己独立的选择,您必须创建新的数组。
要创建新的observableArray
,请再次致电ko.observableArray
。要创建原始列表的副本,(请注意,对象引用仍然相同!),我已使用slice
。
修改强>
上面的方法将组件与原始数组分离。如果你想保持关系而不是修改源,那么你可以做什么:
在您的组件中:
self.myItems = ko.observableArray([]);
self.items = ko.pureComputed(function() {
return params.items().concat(self.myItems());
});
您推送到myItems
,这将触发计算的更新。对源可观察数组的任何更改也会触发更新。如果愿意,您甚至可以添加排序。