淘汰赛:多个视图模型订阅Json

时间:2015-10-28 04:33:38

标签: knockout.js knockout-mapping-plugin

我希望能够组织我的Knockout代码,如下所示:

  • 导入'Master Json'文件并映射它。
  • 创建多个视图模型,每个模型都引用“Master Json”文件的特定部分。
  • 将每个视图模型中的所有可观察对象绑定到'Master Json'文件的值。

是否可以使用 ko.subscribable 将所有订阅我的json文件作为主值?

或者如何从每个视图模型函数内部移动$ .getJSON(和save)函数?我可以创建一个函数,以便getJSON结果可以在每个视图模型中重复使用吗?

function ApplesViewModel ( data ) {

    // ko.observables here 

    //Get Json
    $.getJSON("json/masterJson.json", function(allData) {
        var mappedSlides = $.map(allData, function(item) { return new Slide(item) });
        self.slides(mappedSlides);
    });    

    //Save Json
    self.save = function() {
        $.ajax("/masterJson", {
            data: ko.toJSON({ slides: self.slides }),
            type: "post", contentType: "application/json",
            success: function(result) { alert(result) }
        });
    }; 
}

function BananasViewModel( data ) {
    //same as ApplesViewModel but with different observables
}

function CarrotsViewModel( data ) {
    //same as ApplesViewModel but with different observables
}

ko.applyBindings(new ApplesViewModel());
ko.applyBindings(new BananasViewModel());
ko.applyBindings(new CarrotsViewModel());

我不想多次导入它,因为我认为每次都会创建一个新副本。它应该只是一个Json文件。当我试图移动它时,我得到的错误是一切都未定义。

也许这是完全错误的做法。每个人都将所有内容都放在一个视图模型中吗它会不会很快混淆?

2 个答案:

答案 0 :(得分:1)

让我为进一步的对话创建一个起点:

function ApplesViewModel(data) {
    self.slides = ko.observableArray($.map(data, function(item) { return new Slide(item) }));
    // setup other properties here 
}

function getFruitViewModel(modelUrl, targetModelHolder) {
    $.getJSON(modelUrl, function(allData) {
        targetModelHolder(new ApplesViewModel(allData));
    });    
}

function saveFruitViewModel(saveModelUrl, targetModelHolder) {
    $.ajax(saveModelUrl, {
        data: ko.toJSON(ko.unwrap(targetModelHolder)),
        type: "post", contentType: "application/json",
        success: function(result) { alert(result) }
    });
}

用法示例:

    var applesViewModel = ko.observable();
    getFruitViewModel("json/masterJson.json", applesViewModel);
    // some work with view model(s)
    saveFruitViewModel("/masterJson", applesViewModel);

如果我误解,请纠正我。

更新1

创作者功能:

function getFruitViewModel(modelUrl, targetModelHolder, creator) {
    $.getJSON(modelUrl, function(allData) {
        targetModelHolder(creator(allData));
    });    
}

用法:

    getFruitViewModel("json/masterJson.json", applesViewModel, function(data) { return new ApplesViewModel(data); });

答案 1 :(得分:1)

是的,您可以使用ko.subscribable,如果您这样做,请结帐ko.postboxko.subscriable的实用程序包装器。这样您就可以跨视图模型发布您的json。

因此,使用ko.postbox,您将发布订阅到活动/主题。创建一个单独的函数,用于从服务器加载JSON,并使此发布事件,并且该事件的所有订阅者都将知道收到数据的时间。

function DataLoader(){
  var self = this;
  self.loadJSON = function(){
    //Load JSON using getJSON from server and publish event "JsonDataLoaded"
    setTimeout(function(){
          ko.postbox.publish("JsonDataLoaded", data);
    }, 3000)
  };
}

var loader = new DataLoader();
loader.loadJSON();

因此,无论何时需要新数据,都会调用loader.loadJSON' and upon success, that will yield event/topic 'JsonDataLoaded。然后,您可以在视图模型中订阅此事件。像

这样的东西
function ApplesViewModel(data) {
  var self = this;

  ko.postbox.subscribe("JsonDataLoaded", function(newData){
    ko.mapping.fromJS(newData,{},self);
  },self,true);

}

CodePen参考。