CoffeeScript, нокаут и наблюдаемый
У меня есть следующий CoffeeScript для создания Javascript для Knockoutjs
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
Хорошо, это может быть одна из проблем, с которыми сталкивается CoffeeScript:
class NewsItem
content: ko.observable("")
Здесь вы создаете новый класс со свойством "content", которое является наблюдаемым объектом. Это компилируется в следующий JavaScript:
var NewsItem = (function() {
function NewsItem() {}
NewsItem.prototype.content = ko.observable("");
return NewsItem;
})();
Как вы теперь видите, свойство "контент" прикрепляется к прототипу. Это означает: есть только одно наблюдаемое, созданное, а не одно для каждого экземпляра. Поэтому всякий раз, когда вы выполняете new NewsItem
, конструктор обновляет эту единицу, наблюдаемую в прототипе, следовательно, одно и то же значение для всех экземпляров.
Чтобы решить эту проблему, просто создайте наблюдаемое в конструкторе. Таким образом, он привязывается к экземпляру, а не прототипу:
class NewsItem
constructor: (data,dispForm) ->
@content = ko.observable data.get_item("content")
Скомпилируется в (соответствующая часть):
this.content = ko.observable(data.get_item("content"));