Мне нужно отредактировать массив целых чисел в веб-приложении, используя Javascript и Knockout.js. Этот массив будет привязан к текстовым полям, и всякий раз, когда значение любого текстового поля будет изменено, массив будет обновлен. И когда он обновляется, вычисляется сумма элементов.Отслеживание изменений - наблюдаемый элемент в наблюдаемом массиве
Это моя первая попытка: http://jsfiddle.net/ZLs2A/0/. Его не работает (значение суммы не обновляется при вводе нового значения для любого элемента). Вот когда я понял, что наблюдаемыйArray будет запускать функцию sum только после вставки или удаления элементов.
<h4>Numbers</h4>
<button data-bind="click: add">Add</button>
<ul data-bind="foreach: numbers">
<li>
<input data-bind="value: $data"></input>
</li>
</ul>
<span data-bind="text: sum"></span>
function MyViewModel() {
var self = this;
self.numbers = ko.observableArray([
1,
2,
3
]);
self.sum = ko.computed(function() {
var items = self.numbers();
var total = 0;
for (var i = 0; i < items.length; i++) {
total += parseInt(items[i]);
}
return total;
});
self.add = function() {
var lastIndex = self.numbers().length - 1;
var lastValue = self.numbers()[lastIndex];
self.numbers.push(lastValue + 1);
}
}
ko.applyBindings(new MyViewModel());
Моя следующая попытка была сделать каждый элемент в массиве чисел наблюдаемой (http://jsfiddle.net/ZLs2A/1/). Это не сработало.
self.numbers = ko.observableArray([
ko.observable(1),
ko.observable(2),
ko.observable(3)
]);
Моя последняя попытка была создать новый класс (ArrayItem) удерживать значение элемента внутри наблюдаемого свойства. На этот раз это сработало! (http://jsfiddle.net/ZLs2A/3/)
<h4>Numbers</h4>
<button data-bind="click: add">Add</button>
<ul data-bind="foreach: numbers">
<li>
<input data-bind="value: value"></input>
</li>
</ul>
<span data-bind="text: sum"></span>
function MyViewModel() {
var self = this;
self.numbers = ko.observableArray([
new ArrayItem(1),
new ArrayItem(2),
new ArrayItem(3)
]);
self.sum = ko.computed(function() {
var items = self.numbers();
var total = 0;
for (var i = 0; i < items.length; i++) {
total += parseInt(items[i].value());
}
return total;
});
self.add = function() {
var lastIndex = self.numbers().length - 1;
var lastItem = self.numbers()[lastIndex];
var newValue = parseInt(lastItem.value()) + 1;
self.numbers.push(new ArrayItem(newValue));
}
}
function ArrayItem(value){
var self = this;
self.value = ko.observable(value);
}
ko.applyBindings(new MyViewModel());
Однако, я не хотел, чтобы создать этот новый класс ArrayItem. Есть ли способ избавиться от него, заставив пример работать с наблюдаемым массивом наблюдаемых элементов (например, моя вторая попытка)?
Автор KO ответил [это (? Можно дублировать) вопрос] (http://stackoverflow.com/questions/9510539/knockout-js-how-to-correctly-bind-an -observablearray), в основном аналогично вашей окончательной версии с конструктором ArrayItem (он просто встроил эту функцию). Ответ - год, поэтому, возможно, что-то изменилось в среднем ... Если это не так, похоже, вы уже ответили на свой вопрос. – Jeroen
Возможно, стоит упомянуть интеграцию Breeze.js с Knockout.js, которая добавляет отслеживание изменений среди других вещей. http://www.breezejs.com/ –