Nakavt arasındaki fark Görünüm Nesne değişmezi olarak işlevler olarak bildirilen modeller


195

Nakavt js Ben Görünüm Modelleri ya da olarak beyan bakın:

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

ko.applyBindings(viewModel );

veya:

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

ko.applyBindings(new viewModel ());

Varsa ikisi arasındaki fark nedir?

Ben buldunuz Bu tartışmayı grubunu google knockoutjs üzerinde ama gerçekten bana tatmin edici bir cevap vermedi.

Modeli bazı verilerle başlatmak istersem bir neden görebilirim, örneğin:

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

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

Ama bunu yapmazsam hangi stili seçtiğim önemli mi?


Bir fark olduğuna inanmıyorum. Genellikle yapıcı modelini kullanırım, çünkü sıklıkla bildirmeyi tercih ettiğim yöntemler vardır prototype(örneğin, sunucudan veri alır ve görünüm modelini buna göre günceller). Ancak bunları açıkça bir nesne değişmezinin bir özelliği olarak ilan edebilirsiniz, bu yüzden gerçekten bir fark göremiyorum.
James Allardice

4
Bu, nakavt ile ilgisi yoktur ve JavaScript'teki özel nesnelerin somutlaştırılması kolaylığıyla ilgili her şey
zzzzBov

1
@Kev viewModel bir vartor işlevi ise, tıpkı var PersonViewModel = function () {...} gibi UpperCase'de yazarsınız;
Elisabeth

Yanıtlar:


252

Görünüm modelinizi tanımlamak için bir işlev kullanmanın birkaç avantajı vardır.

Ana avantajı, thisoluşturulan örneğe eşit olan bir değere anında erişebilmenizdir . Bu, şunları yapabileceğiniz anlamına gelir:

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

Böylece, hesaplanan gözlemlenebiliriniz thisfarklı bir kapsamdan çağrılsa bile uygun değerine bağlanabilir .

Bir nesne değişmeziyle şunları yapmanız gerekir:

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

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

Bu durumda şunu kullanabilirsiniz viewModelsiz, nesnesi değişmez içinde tanımlamak olamazdı bu yüzden bilgisayarlı gözlemlenebilir doğrudan, ancak (varsayılan olarak) hemen değerlendirilir olsun demek viewModelnesne değişmezi kapalı sonrasına kadar tanımlı değil. Birçok kişi, görünüm modelinizin oluşturulmasının tek bir çağrıda yer almamasını sevmez.

thisHer zaman uygun olmasını sağlamak için kullanabileceğiniz başka bir desen , işlevde uygun değere eşit bir değişken ayarlamak thisve bunun yerine kullanmaktır. Bu şöyle olurdu:

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

Şimdi, tek bir öğenin ve çağrının kapsamındaysanız $root.removeItem, değeri thisaslında o düzeyde bağlanan veriler olacaktır (bu öğe olacaktır). Bu durumda kendini kullanarak, genel görünüm modelinden kaldırıldığından emin olabilirsiniz.

bindModern tarayıcılar tarafından desteklenen ve desteklenmiyorsa KO tarafından eklenen başka bir seçenek kullanmaktır . Bu durumda, şöyle görünecektir:

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

Bu konuda söylenebilecek çok daha fazlası ve keşfedebileceğiniz birçok desen (modül deseni ve ortaya çıkan modül deseni gibi), ancak temel olarak bir işlevi kullanmak, nesnenin nasıl oluşturulduğu ve referans verme yeteneği üzerinde daha fazla esneklik ve kontrol sağlar. örneğe özel değişkenler.


1
Mükemmel cevap. Ben sık sık viewmodels gibi karmaşık nesneler için bir fonksiyon (ifşa modülü desen kullanarak) kullanın. Ama basit modeller için, her şeyi tek bir yerde işleyebilmem için bir işlev kullanıyorum.
John Papa

1
@JohnPapa - sadece nakavtta PluralSight videonuzu izliyorsunuz (yarı yarıya biraz fazla - ve tesadüfen, nesne değişmezi işlevine ilişkin bölümü izledim). Gerçekten aferin ve kuruş damla yardımcı oldu. Sadece bunun için bir aylık abonelik değer.
Kev

@Kev - Teşekkürler. Bundan değer elde ettiğine sevindim. Bazıları bu modülü gerçekten bir Nakavt konsepti değil, daha fazla JavaScript modeli olarak umursamayacak. Ama Knockout ile daha da ileri gittiğimde, bu kavramların gerçekten daha temiz ve istikrarlı bir kod oluşturmama yardımcı olduğunu buldum. Her neyse, hoşuna gittiğine sevindim :)
John Papa

self.items = ko.observableArray () olmamalı; ikinci örnekte? Bunu kullandın, doğru mu?
JackNova

1
@JackNova yapıcı işlevinde selfve thisaynıdır, yani her ikisi de eşdeğer olacaktır. RemoveItem işlevinde, bir alt öğe bağlamında yürütüldüğünde artık geçerli örnek olmayacağı için selfdaha kullanışlı hale gelir this.
RP Niemeyer

12

Benzer olsa da, farklı bir yöntem kullanın:

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

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

Birkaç neden:

  1. Kullanmayın this, içinde kullanıldığında karışıklık olabilir ko.computedvb.
  2. Benim viewModel bir singleton, birden fazla örnek oluşturmak gerekmez (yani new viewModel())

Bu yanlış değilse modül modelini ortaya çıkarır. Güzel cevap ama soru bu modelle ilgili değildi.
Phil

@paul: Eski ileti dizisini istediğim için üzgünüm. u dedi My viewModel is a singleton, I don't need to create multiple instances (i.e. new viewModel()) ama ne u u söylemeye çalışıyorum ne söylemeye çalışıyorum I don't need to create multiple instances daha fazla kullanım ile gelebilir böylece bir yaklaşım avantajı anlayabiliyorum. teşekkürler
Mou

IMO, ViewModel'i bir olarak ilan etmenizin nedenlerinden biri, bir functionkereden fazla yürütmenizdir. Ancak, benim örneğimde, hemen çağrılmış anonim bir işlevdir, bu yüzden birden fazla oluşturulmaz. Yukarıdaki örnekte Nesne Değişmezine çok benzer, ancak size daha fazla yalıtım sağlar
paulslater19
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.