使用Knockout时,是否应在模型或视图模型中发生数据加载

时间:2012-11-05 20:03:53

标签: javascript mvvm knockout.js

将你的ajax调用放在你的Knockout ViewModel中或者它应该放在模型中是明智的吗?我想出了一些方法,但没有一个感觉完全正确。

方法1 - 仅限ViewModel

window.someDataVM = function() {
   var self = this;

    //used to enable loading indicator
    self.pendingLoad = ko.observable(true);

    self.myData = ko.observableArray();

    self.load = function() {
        //make ajax call and populate myData observable array
    }     
}

优点

  • 最简单的代码结构 - 更易于维护

缺点

  • 无需重复使用数据检索

方法2 - 使用回调的模型和ViewModel

   window.someDataVM = function() {
       var self = this;

        //used to enable loading indicator
        self.pendingLoad = ko.observable(true);

        self.myData = ko.observableArray();

        self.load = function() {            
            someDataM.load(function(data) {
                //populate myData observable array
            });
        }     
    }

    window.someDataM = function() {
       return {               
          load: function(callback) {
             //get data via ajax and return via callback
          }
       }
    }

优点

  • 在数据检索上更多代码重用(即加载someData的一个地方)

  • 接近3的简单界面

缺点

  • 使用回调

方法3 - 使用淘汰模型的模型和ViewModel

window.someDataVM = function() {
       var self = this;

        //used to enable loading indicator
        self.pendingLoad = ko.observable(true);

        self.myData = ko.observableArray();

        self.load = function() {
            someDataM.load();
        }

        someDataM.isLoaded.subscribe(function(isLoaded) {
            if (isLoaded)  {
               //populate observable array
            }
        });     
}



window.someDataM = function() {
     return {
          isLoaded: ko.observable(false);
          items: [],
          load: function() {
             //get some data, populate items, set isLoaded
          }
     }
    }();

优点

  • 不使用回叫
  • 保持数据代码集中

缺点

  • 拥有大量数据入口点(即LoadById,LoadByName等等)会很复杂。

1 个答案:

答案 0 :(得分:3)

我个人对自动加载虚拟机感到不舒服。因此,我建议首先加载数据(模型),然后将其传递给VM。

从概念上讲,它会是这样的:

function loadData() {
    //load data, can be asynchronously. Then callback
    callback(data);
}

function callback(data) {
    var vm = new someDataVM(data);
    //do something with VM.
    ko.applyBindings(vm);
}

当VM由其他VM(多屏幕应用程序)创建时,这种方法更有意义。此外,这种方法通过建立逻辑依赖链来强调模型 - 视图 - 视图模型分离:

View => ViewModel => Model

但是,VM可以重新加载数据或对用户交互进行异步调用。例如用户可以单击页面上再次加载当前时间的按钮。这些类型的交互显然会发生在现有的vm内部。但这个问题与初始负载有关,我就是这样做的。