2012-06-27 157 views
10

我有以下的CoffeeScript產生的JavaScript Knockoutjs的CoffeeScript,敲除觀察到

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 

要渲染HTML我使用此代碼

<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> 

然而,在HTML的所有項目顯示的值添加到集合中的最後一個NewsItem。

任何提示?

回答

20

好吧,這可能是CoffeeScript的有缺陷之一:

class NewsItem 
    content: ko.observable("") 

在這裏,你要創建一個屬性「內容」是可觀察到的對象的新類。編譯成以下JavaScript代碼:

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

正如您現在所看到的,屬性「content」附加到原型。這意味着:只有一個觀察值被創建,而不是每個實例。因此,無論何時您執行new NewsItem,構造函數都會更新此原型中的單個觀察值,因此所有實例的值都相同。

要解決這個問題,只需在構造函數中創建observable即可。這樣一來,它得到的附加到實例,而不是該原型:

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

編譯成(相關部分):

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

我覺得這始終是它應該怎麼做。 – Tyrsius

+0

@Tyrsius這取決於 - 如果你想爲每個特定實例創建一個自己的類成員(我必須同意,你會在大多數時間需要),那麼是的。你只需要知道差異。 – Niko

+3

我想有些時候你想要一個靜態屬性,但這應該是例外,而不是規則。 – Tyrsius