Подтвердить что ты не робот

Разница между нокаутом Просмотр моделей, объявленных как объектные литералы против функций

В нокауте js я вижу модели просмотра, объявленные как:

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

ko.applyBindings(viewModel );

или

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

ko.applyBindings(new viewModel ());

Какая разница между ними, если они есть?

Я нашел эту дискуссию в группе goockoutjs google, но это не дало мне удовлетворительного ответа.

Я вижу причину, если я хочу инициализировать модель некоторыми данными, например:

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

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

Но если я не делаю, это имеет значение, какой стиль я выбираю?

4b9b3361

Ответ 1

Существует несколько преимуществ использования функции для определения вашей модели представления.

Основное преимущество заключается в том, что у вас есть немедленный доступ к значению 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 не определяется до тех пор, пока объект буквально закрыт. Многим не нравится, что создание вашей модели представления не инкапсулировано в один вызов.

Другим шаблоном, который можно использовать для обеспечения соответствия 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);
};

В этой теме может быть сказано гораздо больше, и многие шаблоны, которые вы могли бы изучить (например, шаблон модуля и раскрытие шаблона модуля), но в основном используя функцию, дают вам большую гибкость и контроль над тем, как создается объект, и способность ссылаться на переменные, которые являются частными для экземпляра.

Ответ 2

Я использую другой метод, хотя похожий:

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

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

Пара причин:

  • Не использовать this, что может привести к путанице при использовании в ko.computed и т.д.
  • My viewModel - одноэлементный, мне не нужно создавать несколько экземпляров (т.е. new viewModel())