Javascript 同一页面上的多个KnockoutJs组件分别运行

Javascript 同一页面上的多个KnockoutJs组件分别运行,javascript,knockout.js,Javascript,Knockout.js,我是一个新手,在一个页面上有一个组件的多个实例 后台。组件从数据服务动态获取对象数组。根据用户的操作,组件可能需要重新渲染阵列(提供新对象),因此阵列是可观察的 问题。页面上必须有多个组件实例,但它们必须独立工作。即使最初它们接收相同的对象数组 我创建了一个简单的例子来说明这个问题 HTML 模拟数据服务调用: 拉动 构成部分1: 构成部分2: JavaScript ko.components.register("item-picker", { viewModel: function(pa

我是一个新手,在一个页面上有一个组件的多个实例

后台。组件从数据服务动态获取对象数组。根据用户的操作,组件可能需要重新渲染阵列(提供新对象),因此阵列是可观察的

问题。页面上必须有多个组件实例,但它们必须独立工作。即使最初它们接收相同的对象数组

我创建了一个简单的例子来说明这个问题

HTML

模拟数据服务调用:
拉动
构成部分1: 构成部分2:
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());
ko.components.register(“项目选择器”{
viewModel:函数(参数){
var self=这个;
self.items=参数项;
self.addPerson=函数(){
self.items.push({
名称:“新日期”+新日期()
});
};
},
模板:“添加

” }); //顶层视图模型 var vm=函数(){ var self=这个; self.itemsArray=ko.observearray([]); self.getData=function(){ self.itemsArray([]); self.itemsArray.push({name:'Bert'},{name:'Charles'},{name:'Denise'}); }; }; 应用绑定(新vm());
该示例也可在JSFIDLE上获得:

编辑 我应该提到数据服务调用是异步的,数据可能会在页面加载之后接收,并且用户可以强制重新检索数据(例如使用不同的参数)。我已经相应地更新了JSFIDLE上的代码片段和示例

问题。在JSFIDLE示例中,如何使组件独立工作?
即,向“组件1”添加新名称不应向“组件2”添加名称

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

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

当前结构中有两层:

  • vm.itemsArray中的
    observearray
    实例
  • 底层的、规则的数组
  • 目前,您的所有组件都在通过(1)修改(2)。为了确保每个组件都拥有自己的独立选择,您必须创建新阵列

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

    编辑:

    上述方法将组件与原始阵列解耦。如果要保留关系但不修改源,可以执行以下操作:

    在您的组件中:

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

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

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

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

    当前结构中有两层:

  • vm.itemsArray中的
    observearray
    实例
  • 底层的、规则的数组
  • 目前,您的所有组件都在通过(1)修改(2)。为了确保每个组件都拥有自己的独立选择,您必须创建新阵列

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

    编辑:

    上述方法将组件与原始阵列解耦。如果要保留关系但不修改源,可以执行以下操作:

    在您的组件中:

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

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

    这听起来像是一个非常有前途的解决方案,我的缺点是数据服务调用是异步的,用户可以随时重新触发。我已经更新了我的问题。您知道如何在这种情况下制作数组包装器吗?创建一个名为myItems的可观察数组,addItem将其推送到。创建一个计算数组,该数组对myItems和parent.items()进行合并。使用foreach绑定中的最后一个计算数组。非常感谢,您救了我的周末!:)你的解决方法引导我解决了这个问题。最后一点我必须修复的是DTOs实例化,它现在可以工作了:)这听起来像是一个非常有前途的解决方案,我的缺点是数据服务调用是异步的,用户可以随时重新触发。我已经更新了我的问题。您知道如何在这种情况下制作数组包装器吗?创建一个名为myItems的可观察数组,addItem将其推送到。创建一个计算数组,该数组对myItems和parent.items()进行合并。使用foreach绑定中的最后一个计算数组。非常感谢,您救了我的周末!:)你的解决方法引导我解决了这个问题。我必须修复的最后一点是DTOs实例化,它现在可以工作了:)