将计算属性添加到视图模型及其子项
Add computed properties to a view model and its sub items
我将尝试对我遇到的问题做一个简化的例子。我认为我非常接近解决方案,但我需要你的帮助来完成最后的润色。
假设我有一个如下所示的视图模型:
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);
}
我使用 ko.mapping plugin 从服务器映射一些数据:
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_computed
),但是我无法将计算的 属性 添加到列表项 - computed
属性 在下面的 bar
项上:
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);
Fiddle
我已经调整了你的 fiddle 并让它按照我认为你想要的方式工作 - 它在这里:
https://jsfiddle.net/4s6jsLx1/10/
我所做的主要事情是实现下面描述的模式,以便您可以轻松干净地定义嵌套视图模型,每个视图模型都带有计算,而不会让您的代码陷入困境(请参阅底部关于创建的注释被调用 4 次)--
首先,创建一些虚拟数据,例如
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_foo
(其中 computed_foo() == "1_comp"
关于 create 被调用 4 次,如果您将 console.log 替换为:
console.log('create', options.data);
然后你会看到第3次和第4次调用时,传入的数据都是垃圾。我没有花太多时间弄清楚它的确切来源,但从广义上讲,我认为您的代码在映射和计算如何交互方面变得有点纠结。我的解决方案已按照上述模式完全删除了此创建方法,旨在将计算的创建与映射过程分开。希望它能满足您的需求!
我将尝试对我遇到的问题做一个简化的例子。我认为我非常接近解决方案,但我需要你的帮助来完成最后的润色。
假设我有一个如下所示的视图模型:
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);
}
我使用 ko.mapping plugin 从服务器映射一些数据:
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_computed
),但是我无法将计算的 属性 添加到列表项 - computed
属性 在下面的 bar
项上:
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);
Fiddle
我已经调整了你的 fiddle 并让它按照我认为你想要的方式工作 - 它在这里:
https://jsfiddle.net/4s6jsLx1/10/
我所做的主要事情是实现下面描述的模式,以便您可以轻松干净地定义嵌套视图模型,每个视图模型都带有计算,而不会让您的代码陷入困境(请参阅底部关于创建的注释被调用 4 次)--
首先,创建一些虚拟数据,例如
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_foo
(其中 computed_foo() == "1_comp"
关于 create 被调用 4 次,如果您将 console.log 替换为:
console.log('create', options.data);
然后你会看到第3次和第4次调用时,传入的数据都是垃圾。我没有花太多时间弄清楚它的确切来源,但从广义上讲,我认为您的代码在映射和计算如何交互方面变得有点纠结。我的解决方案已按照上述模式完全删除了此创建方法,旨在将计算的创建与映射过程分开。希望它能满足您的需求!