我正在使用ockout.js迈出第一步。我已经创建了此代码,但我不满意,因为每次更改价格列中的某些内容时,我的self.totals()
函数都不会汇总(仅当我通过添加新的或删除旧的<tr>
更改整个ojit_code时才起作用)。我在哪里弄错了?
jsfiddle
var books = [
{
name : "Javascript",
author : "David Flanagan",
genre : "learning",
price : "100"
},
{
name : "PHP",
author : "Luke Welling",
genre : "learning",
price : "120"
}
/* some more books */
];
var bookModel = function (books) {
var self = this;
var rowId;
self.books = ko.observableArray(books);
var calculate = self.totals = ko.computed(function () {
var total = 0;
for (var i = 0; i < self.books().length; i++) {
total = total + +self.books()[i].price;
}
return total.toFixed(2);
});
self.addBook = function () {
self.books.push({
name: '',
author: '',
genre: '',
price: ''
});
calculate();
};
self.removeBook = function (book) {
self.books.remove(book);
rowId = book.name;
console.log(rowId);
updateLocalStorage();
calculate();
};
function updateLocalStorage() {
var localBook = JSON.parse(localStorage['table']);
for (var i = 0; i < localBook.length; i++) {
if (localBook[i].name == rowId) {
localBook.splice(i, 1);
localStorage.setItem("table", JSON.stringify(localBook));
break;
}
}
}
self.save = function () {
localStorage.setItem("table", JSON.stringify(books));
calculate();
};
};
if (localStorage['table'] == '[]') {
localStorage.clear();
}
if (localStorage['table'] !== undefined) {
var local = JSON.parse(localStorage['table']);
var viewModel = new bookModel(local);
}
else {
var viewModel = new bookModel(books);
localStorage.setItem("table", JSON.stringify(self.books));
}
ko.applyBindings(viewModel);
最佳答案
这是一个经典的误解:一个可观察的数组通知其项的更改,而不是其项的属性。
例如,当整个元素列表被新的元素列表更改,添加元素或删除元素时,可观察数组将通知更改。在您的情况下,如果添加,删除或更改书籍列表,则计算的可观察值将被更新。
如果您需要计算得出的可观察值对图书价格的变化使用react,则需要使price
属性可观察。即您的书本应如下所示:
var books = [
{
name : "Javascript",
author : "David Flanagan",
genre : "learning",
price : ko.observable(100)
},
{
name : "PHP",
author : "Luke Welling",
genre : "learning",
price : ko.observable(120)
},
如果价格不是可观察的价格,ko将无法检测到价格已发生变化,并且这种情况不会发生。
您可以为每本书做这样的事情:
book.price = ko.observable(book.price)
将常规属性转换为可观察属性(可以很容易地在循环中完成)。记住在
addBook
函数上也创建可观察的属性。由于
calculate
是访问可观察数组的计算可观察对象,因此您无需在addBook
和removeBook
中显式调用它,因为此计算的可观察对象会自动订阅它访问的可观察对象,这既是可观察数组本身,也是价格每本书。您可以在updated fiddle中看到所有这些。
我没有更新小提琴以显示其工作原理,但是,如果您尝试序列化或存储这些书,价格将不会降低,因为它们不再是属性,而是功能。因此,您必须逆转该过程,即对于每本书:
book.price = ko.unwrap(book.price)
要么
book.price = book.price()
注意:您应该组织代码,以便在将属性转换为可观察对象时很清楚,反之亦然。如果您不仅对
price
感兴趣,而且对所有属性都感兴趣,则可以使用ko.mapping plugin通过ko.fromJS
和ko.toJS
将属性转换为可观察值,反之亦然。