viewmodel中的viewmodel .prototype .function vs self .function?

时间:2014-10-04 23:18:10

标签: knockout.js viewmodel yeoman-generator

下面的两个代码块在上下文中工作,并且看起来完全在功能上等效。我理解js prototypes相当合适,所以我本身并不是在询问它们(除非唯一的区别)。

相反,比较两种简单的方法将方法放在视图模型上,如下所示, Knockout 有任何影响/差异,例如:约束时间?

  

define([“knockout”,“text!。/ home.html”],function(ko,homeTemplate){//< - An AMD Module

    function HomeViewModel(route) { 
             var self = this; 
             self.message = ko.observable('Snacks!');

             self.eatSomething = function () { 
                  self.message('Yum, a viewmodel snack.'); 
             };   
    }
    return { viewModel: HomeViewModel, template: homeTemplate };
});

与通过原型添加方法:

  

define([“knockout”,“text!。/ home.html”],function(ko,homeTemplate){

    function HomeViewModel(route) {  
             this.message = ko.observable('Snacks!'); 
    };   

    HomeViewModel.prototype.eatSomething = function () { 
             this.message('Yum, the same viewmodel snack, only different?'); 
    };  
    return { viewModel: HomeViewModel, template: homeTemplate }; 
     

});

(代码是通过Yeoman's输出的Knockout generator脚手架的简单模型。它创建了knockout component的锅炉板代码,这是一个相当近期的(KO 3.2),非常受欢迎一个不错的KO组件解释器是here.

1 个答案:

答案 0 :(得分:13)

在第一个示例中,由于函数使用self(设置为对新实例的引用)而不是this,因此无论函数如何被调用/绑定,它总是会正确设置自己的message observable。

在第二个例子中,当正常绑定到像data-bind="click: eatSomething"这样的函数时,你会得到相同的结果。 Knockout调用函数,其值this等于当前数据。

如果你有一个需要从不同的上下文调用该函数的场景(可能你的视图模型有一个你正在使用的with或模板的子对象)。然后你可以使用像data-bind="click: $parent.eatSomething"这样的绑定。 KO仍会调用this等于当前数据(不是$parent)的函数,因此您会遇到问题。

将函数放在原型上的一个好处是,如果你创建了许多HomeViewModel个实例,它们将通过原型共享相同的eatSomething函数,而不是每个实例都有自己的eatSomething函数的副本。这可能不是您方案中的问题,因为您可能只有一个HomeViewModel

您可以通过调用上下文来确保上下文正确:data-bind="click: $parent.eatSomething.bind($parent)。使用此调用,将创建一个新的包装函数,该函数使用适当的上下文(值this)调用原始函数。或者,您也可以在视图模型中绑定它以保持绑定更清晰。无论哪种方式,你确实失去了将它放在原型上的一些价值,因为你正在为每个实例创建包装函数。 "胆量"该函数至少只会在原型上存在一次。

我倾向于在我的代码中使用原型,但毫无疑问,使用self技术(或类似揭示模块模式)可以减少您对this的值的关注。 / p>