Knockout.js 淘汰:多个视图模型订阅Json

Knockout.js 淘汰:多个视图模型订阅Json,knockout.js,knockout-mapping-plugin,Knockout.js,Knockout Mapping Plugin,我希望能够组织我的淘汰代码,如下所示: 导入一个“主Json”文件并映射它 创建多个视图模型,每个视图模型引用“主Json”文件的特定部分 将每个视图模型中的所有可观察对象绑定到“主Json”文件的值 是否可以使用ko.subscribable将所有内容作为主值订阅到我的json文件 或者如何从每个视图模型函数内部移动$.getJSON(和save)函数?我可以创建一个函数,使getJSON结果在每个视图模型中都可以重用吗 function ApplesViewModel ( data )

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

  • 导入一个“主Json”文件并映射它
  • 创建多个视图模型,每个视图模型引用“主Json”文件的特定部分
  • 将每个视图模型中的所有可观察对象绑定到“主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文件。当我尝试移动它时,我会得到错误,即所有内容都是未定义的


也许这是完全错误的方法。是否每个人都将所有内容都放在一个视图模型中?这不是很快就会让人困惑吗?

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

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.subscribable
的实用程序包装器。这将允许您跨视图模型发布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',一旦成功,将生成事件/主题“JsonDataLoaded
”。然后,您可以在视图模型中订阅此事件。差不多

function ApplesViewModel(data) {
  var self = this;

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

}

参考资料。

您的问题不太清楚。尝试从代码中删除对实际问题不重要的部分,同时添加一些代码,使其完全再现您的实际场景/尝试做您认为需要/想要做的事情。请记住:我们没有任何上下文,我们只有问题中的文本。为什么要删除$.getJSON。您是否希望从viewmodel中删除
save
&
Get
,并将其保留在外部某个位置?我不完全知道我问的问题是否正确。我需要一个起点,这样我才能正确开始。编辑了这个问题,希望能增加清晰度。我需要一天左右的时间来理解这个。。。几个问题:为什么设置超时-用于演示或是必要的?如果我有一个示例,那么对所有viewmodels的更新是否也会更新一个Json文件?是的,请设置Timeout进行演示,模拟getJson响应。不确定您所说的
还更新一个Json文件是什么意思?您是指保存回同一个json文件吗?如果是,保存什么以及何时保存?例如,如果用户在applesViewModel中编辑一个值,然后用户在bananasViewModel中编辑一个值,这两个更新是否会反映在同一个Json副本中?我不需要实际保存到服务器。我只需要更新主Json客户端。使用上述方法,编辑将是每个视图模型的本地编辑,不会反映在主Json文件中。谢谢,我从您的回答中了解到,我最好将所有内容都放在一个视图模型中,这将节省我许多天的尝试和错误。您好,TSV,我认为答案是,我应该为每个Json文件使用一个viewModel,我想在其中存储我的信息。听起来对吗?非主题:我根据我们的另一次对话发布了一个新问题,关于淘汰模板,如果你感兴趣:@JenniferMichelle是的,我想如果水果模型是一样的,你可以用一个类来描述每种水果。如果模型不同,您也可以使用“GetFrootViewModel”,但您应该传递一个creator函数(更新1)。