Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/git/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Knockout.js 向视图模型及其子项添加计算特性_Knockout.js_Knockout Mapping Plugin - Fatal编程技术网

Knockout.js 向视图模型及其子项添加计算特性

Knockout.js 向视图模型及其子项添加计算特性,knockout.js,knockout-mapping-plugin,Knockout.js,Knockout Mapping Plugin,我要试着用一个简单的例子来说明我遇到的问题。我想我很快就能找到解决办法了,但我需要你的帮助来完成最后的润色 假设我有一个如下所示的viewmodel: function viewModel(){ var self = this; self.foo = ko.observable(); self.bars = ko.observableArray(); } function bar(data){ var self = this; self.baz = ko

我要试着用一个简单的例子来说明我遇到的问题。我想我很快就能找到解决办法了,但我需要你的帮助来完成最后的润色

假设我有一个如下所示的viewmodel:

function viewModel(){
    var self = this;
    self.foo = ko.observable();
    self.bars = ko.observableArray();
}

function bar(data){
    var self = this;
    self.baz = ko.observable();
    ko.mapping.fromJS(data, mapperSettings, self);
}
我使用映射来自服务器的一些数据:

var mapperSettings = {
     bars: {
        create: function(options) {
            return new bar(options.data);
        }
    }
};    

var dummyData = {
    foo: '1',
    bars: [{ baz: 1 }, { baz: 2 }]
};

var vm = new viewModel();
ko.mapping.fromJS(dummyData, mapperSettings, vm);
到目前为止一切都很好

现在,我想用一些额外的计算属性来预兆视图模型及其项。我已成功地将其添加到视图模型中(
something\u computed
如下),但我无法将计算属性添加到列表项-
computed
属性添加到
栏上的
项下:

var settings = {  
  create: function(options) {

    var model = ko.mapping.fromJS(options.data, {
      bars: {
        create: function (options) {
          // why is this callback called 4 times and not 2?
          var self = options.data;

          self.computed = ko.computed(function(){
              return this.baz() + ' comp';
          }, self);

          return self;
        }
      }
    });

    model.something_computed = ko.computed(function(){
      return this.foo() + '...';
    }, model);

    return model;
  }
};

var newViewModel = ko.mapping.fromJS(vm, settings);

ko.applyBindings(newViewModel);

我已经调整了你的小提琴,让它按照我认为你想要的方式工作-它在这里:

我所做的主要工作是实现下面描述的模式,以便允许您轻松、清晰地定义每个带有Computed的嵌套视图模型,而不会让代码陷入困境(请参阅底部关于调用4次create的注释)--

首先,创建一些虚拟数据,例如

data = {foo: 1}
然后,为将保存此虚拟数据的视图模型创建视图模型定义。在这里定义您的计算结果。您通常不需要为
foo
定义一个可观察对象,因为映射插件将为您创建一个可观察对象,但因为您从计算中引用它,所以在这种情况下,您确实需要定义它:

function viewModel() {
    var self = this
    self.foo = ko.observable()
    self.computed_foo = ko.computed(function() {
        return self.foo() + " comp"
    })
}
然后将其实例化为一个空白视图模型,以获得一个实例,该实例具有计算的:

blank_vm = new viewModel()
最后,使用ko.mapping用数据填充它。本例提供了
{}
作为空白设置对象,但在fiddle中,我使用您的适当设置对象来创建条形图:

vm = ko.mapping.fromJS(data, {}, blank_vm)
vm
现在有两个属性,
foo
(其中
foo()==1
)和
computed\u-foo
(其中
computed\u-foo()==1


关于create被调用4次,如果将console.log替换为:

console.log('create', options.data);

然后在第3次和第4次调用时,您会看到,传入的数据是垃圾。我没有花太多时间研究它的确切来源,但从广义上讲,我认为您的代码在映射和计算的交互方式方面有点纠结。我的解决方案完全通过遵循上面概述的e模式,其目的是将计算机的创建与映射过程分开。希望它能满足您的需要!

请参见?@RoyJ感谢您的链接。从各种SO线程中我可以看出,我在上面的上次更新中正确地进行了映射。或者我遗漏了什么?我无法理解为什么
create
回调调用了两次以上…我想你应该让你的create函数创建一个新对象,而不仅仅是修改并返回你收到的东西。我不知道为什么它调用了四次,但最后两次没有一个
baz
,所以你可以短路它们。是的,我也这么认为。但无论如何,我不能理解它被调用4次的原因。谢谢你有没有尝试过在调试器中单步执行映射代码?是的,我也注意到了“垃圾部分”。我想主要的问题是,正如你所暗示的,我使用了
ko.mapping.fromJS
以及一个已经映射的视图模型,而不是一些“干净的”像解析的JSON这样的数据。当你想到它的时候,这是非常明显的。有时你需要两双眼睛;)谢谢你的描述性回答-我真的很感激!谢谢,很高兴你成功了!我认为关于垃圾产生的原因你是对的,这是有道理的。