具有可观察对象的敲除组件不会更新数据

解块器

我有以下组件:

<template id="fruits-tpl">
    <p>Name: <input data-bind="value: name" /></p>
    <p>Type: <input data-bind="value: color" /></p>
</template>


ko.components.register('fruits', {
    viewModel: function(params) {
        this.name = params.name;
        this.color   = params.color;
    },
    template: { element: 'fruits-tpl' }
});

我正在将这个组件与下面的视图模型一起使用,其中我的可观察列表中的项目属于不同的类型并具有不同的属性:

function Fruit(data) {
    this.name = ko.observable(data.name);
    this.color = ko.observable(data.color);
}
function Dessert(data) {
    this.name = ko.observable(data.name);
    this.packaging = ko.observable(data.packaging);
}
function Vm(){
    var data = [{name:"Apples",color:"Yellow"},{name:"Cookies",packaging:"Box"}];
    this.items = ko.observableArray([new Fruit(data[0]),new Dessert(data[1])]);
    this.items.choice = ko.observable(this.items()[0]);
}

每当我更改输入框中的文本时,此组件就会很好地工作,并且基础数据也会更新:

<div data-bind="component: {name: 'fruits', params: items.choice}"></div>

现在,我想将可观察对象的逻辑封装到组件本身中,因此我以这种方式更改了组件:

ko.components.register('fruits', {
    viewModel: function(params) {
        this.name = ko.observable(params.name);
        this.color   = ko.observable(params.color);
    },
    template: { element: 'fruits-tpl' }
});

...现在我只在内部有可观察的item.choice数据:

function Vm(){
    var data = [{name:"Apples",color:"Yellow"},{name:"Cookies",packaging:"Box"}];
    this.items = ko.observableArray(data);
    this.items.choice = ko.observable(this.items()[0]);
}

为什么我的第二个示例中的主视图模型中的基础数据没有更新,尽管item.choice仍然可以观察到?我确定我缺少一些概念,也许我的可观察数组中的每个项目也应该是可观察的,但是我不知道是否有办法使第二个示例工作。

第一个示例:http : //jsfiddle.net/5739ht0q/2/第二个示例:http : //jsfiddle.net/079tx0nn/

解块器

有几种方法可以将数据更新回主视图模型,如下所示。

但是首先,让我们稍微完善一下主视图模型。

function Vm(data) {
  var self = this;
  self.items = ko.observableArray(ko.utils.arrayMap(data, function(item) {
    return ko.observable(item);
  }));
  self.items.choice = ko.observable(0);
  self.items.choice.data = ko.computed(function() {
    return self.items()[self.items.choice()];
  });
}

快速与肮脏

第一种快速且肮脏的方法是将在主视图模型内部定义的函数传递给组件:

<div data-bind="component: {
    name: 'fruits',
    params: {index: items.choice(), data: items.choice.data(), update: items.update}
}"></div>

在组件内部,我们可以调用函数来保存更改:

self.data = ko.computed(function(){
    params.update(params.index, ko.toJS(self));
});

现在,主视图模型中的更新功能显而易见,无需为此花费更多的时间。

使用可订阅的

第二种方法是使用可订阅的对象沿视图模型建立通信:

ko.intramodels = new ko.subscribable();

从组件,发送通知:

self.data = ko.computed(function(){
  ko.intramodels.notifySubscribers(ko.toJS(self), "updateFruits");
});

主视图模型内的订阅将接收并保存更改,或多或少是这样的:

  ko.intramodels.subscribe(function(newValue) {
    self.items.replace(self.items()[self.items().index], newValue);
  }, self, "updateFruits");

当然这可以通过手工完成上面一样,但伟大的瑞恩·尼迈耶的邮筒库将是最佳的选择,在这里:https://github.com/rniemeyer/knockout-postbox

我测试了这两种解决方案,但是不幸的是,当我激活-淘汰赛3.4中的新功能-推迟更新选项时遇到了一些麻烦:ko.options.deferUpdates = true;当我收到“超出最大调用堆栈大小”错误时。

删除循环依赖

因为我不想放弃并错过淘汰赛3.4的这一新的出色性能增强功能,并且由于此错误也或多或少地意味着,

循环依赖关系是设计错误,请重新考虑实现的某些部分,

我更改了视图模型,以使依赖项跟踪链仅在一个方向上起作用,而对整个组件数据仅使用一个可观察的模型:

ko.components.register('fruits', {
  viewModel: function(params) {
    var self = this;
    self.data = params.peek();
    self.item = {};
    self.item.name = ko.observable(self.data.name);
    self.item.color = ko.observable(self.data.color);
    self.update = ko.computed(function() {
       params(ko.toJS(self.item));
    });
  },
  template: {
    element: 'fruits-tpl'
  }
});

到目前为止,对于嵌套组件而言,这更明显了,这些组件内部具有所有数据处理和可观察的创建,并且主视图模型不必了解子级内部的内容以及原因-只需传递和接收即可。返回一个可观察对象:

<div data-bind="component:{name:'fruits',params:items.choice.data}"></div>

<template id="containers-tpl">
  <div data-bind="foreach: containers">
    <p><input data-bind="textInput: quantity"><span data-bind="text: name"></span></p>
  </div>
</template>

<template id="fruits-tpl">
  <p>Name:<input data-bind="textInput: item.name"></p>
  <p>Color:<input data-bind="textInput: item.color"></p>
  <div data-bind="component:{name:'containers',params:item.containers}"</div>
</template>

这里的关键点是:

  • 将可观察对象传递给组件,而不仅仅是传递数据,并且
  • 打破组件内部参数的依赖链

带有嵌套组件的完整提琴:http : //jsfiddle.net/jo37q7uL/

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

敲除将javascript对象添加到可观察数组

来自分类Dev

克隆具有可观察数组的Knockout对象

来自分类Dev

在ObservableArray基因敲除js中更新可观察值

来自分类Dev

淘汰赛3.2 AMD组件未更新可观察对象

来自分类Dev

绑定为可观察到的敲除时如何更新ckeditor数据?

来自分类Dev

如果其他可观察对象具有映射功能,则转换可观察对象

来自分类Dev

JSON对象数组,用于淘汰具有可观察属性的可观察数组

来自分类Dev

Rx:从具有不同类型的可观察对象创建后续可观察对象(链式观察者)

来自分类Dev

具有bootstrap事件的Angular2不会触发可观察到的更改

来自分类Dev

更改计算的依赖项时,计算出的可观察的敲除不更新值

来自分类Dev

具有可观察对象的敲除组件不会更新数据

来自分类Dev

带有可观察参数的敲除验证扩展了“仅当”

来自分类Dev

为什么订阅相同序列的不同可观察对象时,ReplySubject具有不同的行为?

来自分类Dev

具有Symbol.observable ponyfill的TypeScript可观察对象

来自分类Dev

角度可观察不会自动更新

来自分类Dev

无法绑定可观察数组-敲除

来自分类Dev

如何验证可观察对象是否具有所有必需成员?

来自分类Dev

当敲除中的其他可观察值发生变化时,更新可观察值

来自分类Dev

显示敲除可观察数组的内容

来自分类Dev

从敲除3.2中的自定义组件可观察到的更新

来自分类Dev

带有敲除的jQWidgets数字输入不会更新为可观察到的

来自分类Dev

VueJs如何创建具有可观察属性的对象

来自分类Dev

从多个组件更新服务数据-可观察的订阅

来自分类Dev

敲除的可观察数组排序问题

来自分类Dev

如何完全清空具有可观察属性的可观察对象?

来自分类Dev

如何创建具有间隔的可观察对象

来自分类Dev

KnockoutJS - 带有来自 SQL 服务器的数据的可观察对象的可观察数组

来自分类Dev

敲除计算的可观察写入不更新

来自分类Dev

合并多个可观察对象并更新现有订阅者?

Related 相关文章

  1. 1

    敲除将javascript对象添加到可观察数组

  2. 2

    克隆具有可观察数组的Knockout对象

  3. 3

    在ObservableArray基因敲除js中更新可观察值

  4. 4

    淘汰赛3.2 AMD组件未更新可观察对象

  5. 5

    绑定为可观察到的敲除时如何更新ckeditor数据?

  6. 6

    如果其他可观察对象具有映射功能,则转换可观察对象

  7. 7

    JSON对象数组,用于淘汰具有可观察属性的可观察数组

  8. 8

    Rx:从具有不同类型的可观察对象创建后续可观察对象(链式观察者)

  9. 9

    具有bootstrap事件的Angular2不会触发可观察到的更改

  10. 10

    更改计算的依赖项时,计算出的可观察的敲除不更新值

  11. 11

    具有可观察对象的敲除组件不会更新数据

  12. 12

    带有可观察参数的敲除验证扩展了“仅当”

  13. 13

    为什么订阅相同序列的不同可观察对象时,ReplySubject具有不同的行为?

  14. 14

    具有Symbol.observable ponyfill的TypeScript可观察对象

  15. 15

    角度可观察不会自动更新

  16. 16

    无法绑定可观察数组-敲除

  17. 17

    如何验证可观察对象是否具有所有必需成员?

  18. 18

    当敲除中的其他可观察值发生变化时,更新可观察值

  19. 19

    显示敲除可观察数组的内容

  20. 20

    从敲除3.2中的自定义组件可观察到的更新

  21. 21

    带有敲除的jQWidgets数字输入不会更新为可观察到的

  22. 22

    VueJs如何创建具有可观察属性的对象

  23. 23

    从多个组件更新服务数据-可观察的订阅

  24. 24

    敲除的可观察数组排序问题

  25. 25

    如何完全清空具有可观察属性的可观察对象?

  26. 26

    如何创建具有间隔的可观察对象

  27. 27

    KnockoutJS - 带有来自 SQL 服务器的数据的可观察对象的可观察数组

  28. 28

    敲除计算的可观察写入不更新

  29. 29

    合并多个可观察对象并更新现有订阅者?

热门标签

归档