【问题标题】:Map JSON data to Knockout observableArray with specific view model type将 JSON 数据映射到具有特定视图模型类型的 Knockout observableArray
【发布时间】:2012-04-14 15:26:05
【问题描述】:

有没有办法将 JSON 数据对象映射到可观察数组,然后依次将可观察数组的每个项目初始化为特定类型的视图模型?

我查看了所有 knockout 的文档以及此处的敲除和映射示例,但找不到任何适合我所追求的答案。

所以,我有以下 JSON 数据:

    var data = {
    state : {
        name : 'SD',
        cities : [{
            name : 'Sioux Falls',
            streets : [{
                number : 1
            }, {
                number : 3
            }]
        }, {
            name : 'Rapid City',
            streets : [{
                number : 2
            }, {
                number : 4
            }]
        }]
    }
};

我有以下视图模型:

var StateViewModel = function(){
    this.name = ko.observable();
    this.cities = ko.observableArray([new CityViewModel()]);
}

var CityViewModel = function(){
    this.name = ko.observable();
    this.streets = ko.observableArray([new StreetViewModel()]);
}

var StreetViewModel = function(){
    this.number = ko.observable();
}

是否有可能通过给定的数据结构并使用 Knockout 的映射插件,让生成的 StateViewModel 包含一个填充有 2 个 CityViewModel 的 observableArray,并且每个 CityViewModel 包含一个填充有 2 个 StreetViewModel 的 observableArray?

目前使用映射插件,我能够将其映射到 StateViewModel,但“城市”和“街道”集合填充了通用对象,而不是我的城市和街景模型的实例。

它们最终得到了正确的可观察属性和值,它们不是我的视图模型的实例,而这正是我所追求的。

【问题讨论】:

    标签: json knockout.js knockout-mapping-plugin


    【解决方案1】:

    查看http://jsfiddle.net/pTEbA/268/

    Object.prototype.getName = function() { 
       var funcNameRegex = /function (.{1,})\(/;
       var results = (funcNameRegex).exec((this).constructor.toString());
       return (results && results.length > 1) ? results[1] : "";
    };
    
    function StateViewModel(data){
        this.name = ko.observable();
        ko.mapping.fromJS(data, mapping, this);
    }
    
    function CityViewModel(data) {
        this.name = ko.observable();
        ko.mapping.fromJS(data, mapping, this);
    }
    
    function StreetViewModel(data) {
        this.name = ko.observable();
        ko.mapping.fromJS(data, mapping, this);
    }
    
    var mapping = {
        'cities': {
            create: function(options) {
                return new CityViewModel(options.data);
            }
        },
        'streets': {
            create: function(options) {
                return new StreetViewModel(options.data);
            }
        }
    }
    
    
    var data = { state: {name:'SD', cities:[{name:'Sioux Falls',streets:[{number:1},{number:3}]},
                                            {name:'Rapid City',streets:[{number:2},{number:4}]}]}};
    
    var vm = new StateViewModel(data.state)
    console.log(vm);
    console.log(vm.getName());
    console.log(vm.cities());
    console.log(vm.cities()[0].getName());
    console.log(vm.cities()[0].streets());
    console.log(vm.cities()[0].streets()[0].getName());
    ​
    

    【讨论】:

    • 我确实有一个后续问题:在创建cities 时,看起来create 映射实际上返回了一个CityViewModel 类型的对象,并传递了一个城市对象。如果你想拥有像CitiesViewModel 这样的集合类型并拥有自己的集合方法,你会怎么做?
    • 看起来不错?但是this.$type = '..Model 在构造函数中做了什么?我在在线 Knockout 或 Knockout.mapping 文档中找不到任何关于 $type 属性的信息。
    • $type 实际上并不是必需的......只是为了证明调用了构造函数。
    • 谢谢。这个例子应该在官方的 Knockout 文档中。
    猜你喜欢
    • 2013-03-21
    • 2012-09-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-23
    • 2014-07-31
    • 2018-01-21
    • 1970-01-01
    相关资源
    最近更新 更多