web-dev-qa-db-ja.com

オブジェクトリテラルと関数として宣言されたノックアウトビューモデルの違い

ノックアウトjsでは、次のいずれかとして宣言されたビューモデルが表示されます。

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

ko.applyBindings(viewModel );

または:

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

ko.applyBindings(new viewModel ());

もしあれば、2つの違いは何ですか?

Knockoutjs googleグループで この議論 を見つけましたが、満足のいく答えは得られませんでした。

いくつかのデータを使用してモデルを初期化する場合、理由がわかります。たとえば、次のとおりです。

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

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

しかし、それをしていない場合、どのスタイルを選択するかは重要ですか?

193
Kev

ビューモデルを定義する関数を使用することには、いくつかの利点があります。

主な利点は、作成されるインスタンスに等しいthisの値にすぐにアクセスできることです。これは、次のことができることを意味します。

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);
};

したがって、計算されたオブザーバブルは、別のスコープから呼び出された場合でも、thisの適切な値にバインドできます。

オブジェクトリテラルでは、次のことを行う必要があります。

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

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

その場合、計算されたオブザーバブルでviewModelを直接使用できますが、オブジェクトリテラルが閉じられるまでviewModelが定義されないため、オブジェクトリテラル内ですぐに評価されるので、すぐに評価されます。多くの人は、ビューモデルの作成が1つの呼び出しにカプセル化されないことを嫌います。

thisが常に適切であることを確認するために使用できる別のパターンは、関数内の変数をthisの適切な値に設定し、代わりに使用することです。これは次のようになります。

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

ここで、個々のアイテムのスコープ内で$root.removeItemを呼び出すと、thisの値は、実際にはそのレベルでバインドされているデータ(アイテム)になります。この場合にselfを使用することにより、全体のビューモデルから確実に削除されます。

別のオプションはbindを使用することです。これは、最新のブラウザーでサポートされており、サポートされていない場合はKOによって追加されます。その場合、次のようになります。

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

このトピックと探索できる多くのパターン(モジュールパターンや公開モジュールパターンなど)で言えることははるかに多くありますが、基本的に関数を使用すると、オブジェクトの作成方法と参照機能をより柔軟に制御できます。インスタンスにプライベートな変数。

251
RP Niemeyer

私は別の方法を使用しますが、似ています:

var viewModel = (function () {
  var obj = {};
  obj.myVariable = ko.observable();
  obj.myComputed = ko.computed(function () { return "hello" + obj.myVariable() });

  ko.applyBindings(obj);
  return obj;
})();

いくつかの理由:

  1. thisを使用していないため、ko.computedsなどで使用すると混乱する可能性があります
  2. 私のviewModelはシングルトンです。複数のインスタンスを作成する必要はありません(つまり、new viewModel()
12
paulslater19