Hay un par de ventajas al usar una función para definir su modelo de vista.
La principal ventaja es que tiene acceso inmediato a un valor this
igual a la instancia que se está creando. Esto significa que puedes hacer:
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);
};
Por lo tanto, su observable calculado puede estar vinculado al valor apropiado de this
, incluso si se llama desde un ámbito diferente.
Con un objeto literal, deberías hacer:
var viewModel = {
first: ko.observable("Bob"),
last: ko.observable("Smith"),
};
viewModel.full = ko.computed(function() {
return this.first() + " " + this.last();
}, viewModel);
En ese caso, podrías usar viewModel
directamente en el observable calculado, pero se evalúa de inmediato (por defecto), por lo que no puede definirlo dentro del objeto literal, comoviewModel
que no se define hasta después de que se cerró el literal del objeto. A muchas personas no les gusta que la creación de su modelo de vista no esté encapsulada en una sola llamada.
Otro patrón que puede usar para asegurarse de que this
siempre sea apropiado es establecer una variable en la función igual al valor apropiado this
y usarla en su lugar. Esto sería como:
var ViewModel = function() {
var self = this;
this.items = ko.observableArray();
this.removeItem = function(item) {
self.items.remove(item);
}
};
Ahora, si está dentro del alcance de un artículo individual y llama $root.removeItem
, el valor dethis
será en realidad los datos vinculados a ese nivel (que sería el elemento). Al usar self en este caso, puede asegurarse de que se elimine del modelo de vista general.
Otra opción es usar bind
, que es compatible con los navegadores modernos y agregado por KO, si no es compatible. En ese caso, se vería así:
var ViewModel = function() {
this.items = ko.observableArray();
this.removeItem = function(item) {
this.items.remove(item);
}.bind(this);
};
Hay mucho más que podría decirse sobre este tema y muchos patrones que podría explorar (como el patrón de módulo y el patrón de módulo revelador), pero básicamente el uso de una función le brinda más flexibilidad y control sobre cómo se crea el objeto y la capacidad de referenciar variables que son privadas para la instancia.
prototype
(métodos que a menudo, por ejemplo, obtienen datos del servidor y actualizan el modelo de vista en consecuencia). Sin embargo, obviamente podría declararlos como una propiedad de un objeto literal, por lo que realmente no puedo ver la diferencia.