访问knockout映射插件中的viewmodel

时间:2014-04-22 09:16:00

标签: knockout.js knockout-mapping-plugin

我正在使用knockout映射插件将计算属性添加到可观察数组中的项目。但是,此计算属性依赖于我的viewmodel中的不同属性。

在映射期间创建observable时如何访问viewmodel属性?

请注意,我无法使用options.parent,因为该属性在viewModel中更进一步。

我也无法更改viewmodel,因为它是生成服务器端的。

编辑:

这是一个显示问题的JSFiddle。注释掉的那条线是我需要工作的。

http://jsfiddle.net/g46mt/2/

这就是我现在所拥有的,但显然是一个错误:

var mapping = {
    'Collection': {
        create: function(options) {
            var model = ko.mapping.fromJS(options.data);
            model.Total = ko.computed(function() {
                var result = this.Price() * viewModel.Count(); // :(
                return result;
            }, model);

            return model;
        }
    }
};

var json = { ... large json object ... };
var viewModel = ko.mapping.fromJS(json, mapping);

2 个答案:

答案 0 :(得分:1)

一种可能的解决方案是使用{deferEvaluation: true}选项。因此,只有在viewModel准备好并且实际使用了Total属性时才会计算您的计算函数:

var mapping = {
    'Collection': {
        create: function(options) {
            var model = ko.mapping.fromJS(options.data);
            model.Total = ko.computed(function() {
                var result = this.Price() * viewModel.Count();
                return result;
            }, model, {deferEvaluation: true});
            return model;
        }
    }
};

演示JSFiddle

但是,使用此方法,您可以将视图模型名称与映射选项紧密耦合。因为如果您更改var viewModel = ko.mapping.fromJS(json, mapping);并以不同方式命名viewModel,那么您还必须更新映射配置。

因为没有办法走'父母'#34;映射配置中的链可能对于这种情况,映射插件不是最好的解决方案......

这是一种使用手写视图模型并传递" root"的另一种方法。它需要在哪里:

var MainViewModel = function (json) {    
    ko.mapping.fromJS(json, { 'ignore': ["Foo"] }, this); //map the rest
    this.Foo = new FooViewModel(json.Foo, this);
}

var FooViewModel = function (json, root) {
    ko.mapping.fromJS(json, { 'ignore': ["Bar"] }, this); //map the rest
    this.Bar = new BarViewModel(json.Bar, root);
}

var BarViewModel = function (json, root) {
    ko.mapping.fromJS(json, { 'ignore': ["Collection"] }, this); //map the rest
    this.Collection = ko.mapping.fromJS(json.Collection, {
       create: function(options) {
            var model = ko.mapping.fromJS(options.data);
            model.Total = ko.computed(function() {
                var result = this.Price() * root.Count();
                return result;
            }, model);

            return model;

       }});
}

演示JSFiddle

答案 1 :(得分:1)

使用映射插件,可以从多个源映射。我想你可以做到

var viewModel = ko.mapping.fromJS(json);
viewModel = ko.mapping.fromJS(json, mapping, viewModel),

在第一次映射之后,您将每个Price作为一个可观察的集合。在第二次映射之后,您将拥有Total以及可观察的。

demo i jsfiddle