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

Multiple KnockoutJs components on the same page running individually

本文关键字:KnockoutJs 组件 单独 运行 一页      更新时间:2023-09-26

我是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示例中,我如何使组件独立工作?也就是说,给"Component 1"添加一个新名字不应该给"Component 2"添加一个新名字

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

self.items = ko.observableArray(params.items().slice(0));
https://jsfiddle.net/dx6b6nvy/

在当前的结构中有两层:

  1. vm.itemsArray中的observableArray实例
  2. 底层的常规数组

目前,你所有的组件都通过(1)修改(2)。为了确保每个组件保持自己的,独立的,选择,你必须创建新的数组。

重新调用ko.observableArray创建新的observableArray。为了创建原始列表的副本(注意对象引用仍然是相同的!),我使用了slice .

编辑:

上面的方法将组件与原始数组解耦。如果您想保留关系但不修改源代码,可以这样做:

在你的组件中:

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

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