2012-06-27 11 views
10

Tengo el siguiente CoffeeScript para generar Javascript para KnockoutjsCoffeeScript, Knockout y observables

class NewsItem 
    content: ko.observable("") 
    title: ko.observable("") 

    constructor: (data,dispForm) -> 
     @content data.get_item("content") 
     @title data.get_item("title") 
     @id = data.get_id() 

class NewsItemViewModel 
    collection: ko.observableArray() 

    loadAll: => 
      listEnumerator = items.getEnumerator()   
      while listEnumerator.moveNext() 
       currentItem = listEnumerator.get_current() 
       @collection.push new NewsItem currentItem, @list.get_defaultDisplayFormUrl() 
      return 

$ -> 
    viewModel = new NewsItemViewModel 
    ko.applyBindings viewModel 
    return 

Para representar HTML utilizo este código

<ul id="results" data-bind="template: {name: 'item_template', foreach: collection}"> 
</ul> 
<script id="item_template" type="text/x-jquery-tmpl"> 
<li> 
    <h3><a href="/" data-bind="text: title"></a></h3> 
    <p> 
     <textarea data-bind="value: content"></textarea> 
     <input type="button" value="save" data-bind="enable: content().length > 0"> 
    </p> 
</li> 
</script> 

Sin embargo, en el HTML todos los artículos mostrar los valores de el último NewsItem agregado a la colección.

¿Alguna pista?

Respuesta

20

bien, esto puede ser una de las trampas que tiene CoffeeScript:

class NewsItem 
    content: ko.observable("") 

aquí, estás creando una nueva clase con una propiedad "contenido" que es un objeto observable. Esto se compila en el siguiente JavaScript:

var NewsItem = (function() { 
    function NewsItem() {} 
    NewsItem.prototype.content = ko.observable(""); 
    return NewsItem; 
})(); 

Como puede ver ahora, el "contenido" de la propiedad se adjunta al prototipo. Eso significa que solo hay un observable creado, no uno por instancia. Entonces cada vez que lo haga new NewsItem, el constructor actualiza este único observable en el prototipo, de ahí el mismo valor para todas las instancias.

Para resolver esto, simplemente crea el observable en el constructor. De esta manera, se consigue de asociado con la instancia, no es el prototipo:

class NewsItem 
    constructor: (data,dispForm) -> 
     @content = ko.observable data.get_item("content") 

compila en (parte pertinente):

this.content = ko.observable(data.get_item("content")); 
+0

creo que esto es siempre la forma en que debe hacerse. – Tyrsius

+0

@Tyrsius Depende, si desea un miembro de la clase propia para cada instancia específica (debo estar de acuerdo, querrá eso la mayor parte del tiempo), entonces sí. Solo necesitas saber la diferencia. – Niko

+3

Supongo que habrá ocasiones en que desee una propiedad estática, pero esta debería ser la excepción, no la regla. – Tyrsius

Cuestiones relacionadas