Making a javascript knockout viewmodel without the new keyword

╄→гoц情女王★ 提交于 2020-01-01 18:30:15

问题


I'm looking through the knockout tutorials, and all the examples create the view model using the 'new' keyword:

//from learn.knockoutjs.com
function AppViewModel() {
  this.firstName = ko.observable("Bert");
  this.lastName = ko.observable("Bertington");
  this.fullName = ko.computed(function() {
    return this.firstName() + " " + this.lastName();    
  }, this);
}
ko.applyBindings(new AppViewModel());

I'm trying to avoid using the new keyword, which usually works perfectly ok, but I find trouble getting the fullName computed property to work. This is what I've come up with so far.

function makeViewModel() {
  return {
  firstName: ko.observable("Bert"),
  lastName: ko.observable("Bertington"),
  fullName: ko.computed(function() {
    return this.firstName() + " " + this.lastName();    
  }, this) };
}
ko.applyBindings(makeViewModel());

...which obviously fails since 'this' no longer refers to the local object inside the function passed to computed. I could get around this by creating a variable and store the view model before attaching the computed function and returning it, but if there exists a more elegant and compact solution that doesn't require me to make sure that methods that depend on each other are attached in the correct order, I'd sure like to use that instead.

Is there a better solution?


回答1:


When creating it in a function, it is not necessary to return a new object. Instead you would do:

var ViewModel = function() {
    this.firstName = ko.observable("Bert");
    this.lastName = ko.observable("Bertington");
    this.fullName = ko.computed(function() {
         this.firstName() + " " + this.lastName();
    }, this);
};

Now you have access to the proper this in the computed observable.

If you really do not want to use "new" (there is no reason why you should not in this case), then you could do something like:

var createViewModel = function() { 
    var result = {
        firstName: ko.observable("Bert"),
        lastName: ko.observable("Bertington")
    };

    result.fullName = ko.computed(function() {
        return result.firstName() + " " result.lastName();
    });

    return result;
};



回答2:


You can certainly get around using the new keyword by making the function self invoking, but I think you'd be better off solving the problem of the "this" keyword. I like to show people 3 ways to create viewmodels.

  1. object literal http://jsfiddle.net/johnpapa/u9S93/
  2. as a function http://jsfiddle.net/johnpapa/zBqxy/
  3. with the Revealing Module Pattern http://jsfiddle.net/johnpapa/uRXPn/

When using option 2 or 3 above, it is much easier to deal with the "this" keyword.




回答3:


You can enforce new like so (taken from this great pattern resource)

function Waffle() {
    if (!(this instanceof Waffle)) {
    return new Waffle();
    }

    this.tastes = "yummy";
}

However I am unsure what you mean by

I'm trying to avoid using the new keyword, which usually works perfectly ok, but I find trouble getting the fullName computed property to work. This is what I've come up with so far.

This should work fine, can you show us a concrete example in jsfiddle that doesn't work with using new.

Hope this helps.



来源:https://stackoverflow.com/questions/9744094/making-a-javascript-knockout-viewmodel-without-the-new-keyword

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!