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

Knockout: multiple view models subscribe to Json

我希望能够像这样组织我的 Knockout 代码:

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

或者如何从每个视图模型函数内部移动 $.getJSON(并保存)函数?我可以创建一个函数,以便 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 文件。当我尝试移动它时,出现一切未定义的错误。

也许这是完全错误的做法。每个人都把所有东西都放在一个视图模型中吗?它不会很快变得混乱吗?

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

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); });

是的,您可以为此使用 ko.subscribable,如果您这样做,请查看 ko.postboxko.subscriable 的实用程序包装器。这将允许您跨视图模型发布您的json。

因此使用 ko.postbox,您将发布订阅 events/topics。为从服务器加载 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参考。