声明为对象文字与函数的淘汰赛视图模型之间的区别 [英] Difference between knockout View Models declared as object literals vs functions

查看:18
本文介绍了声明为对象文字与函数的淘汰赛视图模型之间的区别的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

In knockout js I see View Models declared as either:

var viewModel = {
    firstname: ko.observable("Bob")
};

ko.applyBindings(viewModel );

or:

var viewModel = function() {
    this.firstname= ko.observable("Bob");
};

ko.applyBindings(new viewModel ());

What's the difference between the two, if any?

I did find this discussion on the knockoutjs google group but it didn't really give me a satisfactory answer.

I can see a reason if I wanted to initialise the model with some data, for example:

var viewModel = function(person) {
    this.firstname= ko.observable(person.firstname);
};

var person = ... ;
ko.applyBindings(new viewModel(person));

But if I'm not doing that does it matter which style I choose?

解决方案

There are a couple of advantages to using a function to define your view model.

The main advantage is that you have immediate access to a value of this that equals the instance being created. This means that you can do:

var ViewModel = function(first, last) {
  this.first = ko.observable(first);
  this.last = ko.observable(last);
  this.full = ko.computed(function() {
     return this.first() + " " + this.last();
  }, this);
};

So, your computed observable can be bound to the appropriate value of this, even if called from a different scope.

With an object literal, you would have to do:

var viewModel = {
   first: ko.observable("Bob"),
   last: ko.observable("Smith"),
};

viewModel.full = ko.computed(function() {
   return this.first() + " " + this.last();
}, viewModel);

In that case, you could use viewModel directly in the computed observable, but it does get evaluated immediate (by default) so you could not define it within the object literal, as viewModel is not defined until after the object literal closed. Many people don't like that the creation of your view model is not encapsulated into one call.

Another pattern that you can use to ensure that this is always appropriate is to set a variable in the function equal to the appropriate value of this and use it instead. This would be like:

var ViewModel = function() {
    var self = this;
    this.items = ko.observableArray();
    this.removeItem = function(item) {
         self.items.remove(item);
    }
};

Now, if you are in the scope of an individual item and call $root.removeItem, the value of this will actually be the data being bound at that level (which would be the item). By using self in this case, you can ensure that it is being removed from the overall view model.

Another option is using bind, which is supported by modern browsers and added by KO, if it is not supported. In that case, it would look like:

var ViewModel = function() {
    this.items = ko.observableArray();
    this.removeItem = function(item) {
         this.items.remove(item);
    }.bind(this);
};

There is much more that could be said on this topic and many patterns that you could explore (like module pattern and revealing module pattern), but basically using a function gives you more flexibility and control over how the object gets created and the ability to reference variables that are private to the instance.

这篇关于声明为对象文字与函数的淘汰赛视图模型之间的区别的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆