CoffeeScript,Knockout&可观察

时间:2012-06-27 21:31:31

标签: knockout.js coffeescript

我有以下CoffeeScript为Knockoutjs生成Javascript

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的值。

任何提示?

1 个答案:

答案 0 :(得分:20)

好吧,这可能是CoffeeScript的一个陷阱:

class NewsItem
    content: ko.observable("")

在这里,您将创建一个具有属性“content”的新类,该属性是一个可观察对象。这将编译为以下JavaScript:

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

正如您现在所看到的,属性“content”附加到原型上。这意味着:只创建了一个observable,而不是每个实例一个。因此,无论何时执行new NewsItem,构造函数都会更新原型中的单个observable,因此所有实例的值都相同。

要解决此问题,只需在构造函数中创建observable即可。这样,它就会附加到实例上,而不是原型:

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

编译成(相关部分):

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