单个运行的同一页面上的多个KnockoutJs组件

时间:2016-10-14 13:30:39

标签: javascript knockout.js

我是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”

1 个答案:

答案 0 :(得分:0)

在构造函数中创建一个新的可观察数组包装器内部数组:

self.items = ko.observableArray(params.items().slice(0));

https://jsfiddle.net/dx6b6nvy/

目前的结构中有两层:

  1. observableArray
  2. 中的vm.itemsArray个实例
  3. 基础的常规数组
  4. 目前,所有组件都通过(1)修改(2)。为了确保每个组件都有自己独立的选择,您必须创建新的数组。

    要创建新的observableArray,请再次致电ko.observableArray。要创建原始列表的副本,(请注意,对象引用仍然相同!),我已使用slice

    修改

    上面的方法将组件与原始数组分离。如果你想保持关系而不是修改源,那么你可以做什么:

    在您的组件中:

    self.myItems = ko.observableArray([]);
    self.items = ko.pureComputed(function() {
      return params.items().concat(self.myItems());
    });
    

    您推送到myItems,这将触发计算的更新。对源可观察数组的任何更改也会触发更新。如果愿意,您甚至可以添加排序。