挖空绑定不会更新模型

Knockout binding does not update model

本文关键字:更新 模型 绑定      更新时间:2023-09-26

我才开始使用Knockout,但我已经对WPF中应用的MVVM有经验。我遇到的问题是包裹模型对象的挖空视图模型不会更新该原始模型。这里有一个小例子:

.HTML

<select name="size" id="sel-size" data-bind="options: sizes, value: size"></select>

.JS

// default settings
var settings = {
    size: 5
};
// settings view model
var settingsVM = function () {
    return {
        sizes: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
        size: ko.observable(settings.size)
    }
}();
// subscribe to changes
settingsVM.size.subscribe(function() {
    alert("Model: " + settings.size + " / VM: " + settingsVM.size());
})
ko.applyBindings(settingsVM);

在 JSFiddle 中查看

更改下拉选择时,仅更新视图模型中的settingsVM.size(),但模型中的settings.size保持不变。

似乎使用引用初始化observable不会将该引用保留为属性访问器的支持字段。关于淘汰赛的MVVM方式,我错过了什么?

当您更改选择的值时,它实际上覆盖了可观察大小的内容。如果要设置后备字段类型排列,则必须使用具有读/写功能的计算可观察量。

此外,如果您确实想要更新原始的"settings"对象,则需要处理它,而不是单独的 settings.size 属性。像这样的事情将使原始模型与选择保持一致:

// settings view model
var settingsVM = function () {
  var self=this;
  self.settings = ko.observable({
    size: 5
  });
  self.sizes =   [{size:1},{size:2},{size:3},{size:4},{size:5}];
  self.size = ko.computed({
          read:function(){
            return self.settings();
          },
          write:function(val){
            self.settings(val);
   }});
   self.size.subscribe(function() {
            alert("Model: " + self.settings().size + " / VM: " + self.size().size);
        });
};
ko.applyBindings(new settingsVM());

JSFiddle

它不更新的原因是因为你的settings.size不是可观察的,并且你的代码不提供使用settings.size作为 html 中的选定大小。

// default Model for settings
function settings(){
    this.size = ko.observable(5);
}
// settings view model
var settingsVM = function () {    
    return {
        sizes: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
        settings: new settings()
    }
}();
// subscribe to changes
settingsVM.settings.size.subscribe(function() {
    alert("model: " + settingsVM.settings.size());
})
ko.applyBindings(settingsVM);

在此处查看更新的小提琴

Knockout的肮脏小秘密是它不是真正的MVVM。它没有独立于视图建模的数据建模结构,因此它只是 VVM。在普通的应用程序设计中,数据模型位于服务器上,应用程序中的"模型"是一组简单的 AJAX 例程,用于将其部分引入视图模型。Knockout与AJAX无关,所以如何处理应用程序的这一部分取决于你(但它通常非常简单)。

在您的问题中,您希望模型自动更新以反映相应的视图模型元素。这是多余的;目前尚不清楚您是否需要单独的内容来仅从视图模式复制值。视图模型可以只包含模型。但是,如果你有更多的模型问题要做,所以你确实需要将模型元素收集在一个结构中,那么Will Jenkins关于使用subscribe的建议是响应视图模型中变化的最直接方法。

在下面的评论中,Will Jenkins 提到了 Knockout 提供的用于在 JSON 和可观察量之间进行转换的实用程序函数。这些对于在模型和视图模型之间来回迁移也很有帮助。

参见:ko.mapping