我正在使用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是访问可观察数组的计算可观察对象,因此您无需在addBookremoveBook中显式调用它,因为此计算的可观察对象会自动订阅它访问的可观察对象,这既是可观察数组本身,也是价格每本书。

您可以在updated fiddle中看到所有这些。

我没有更新小提琴以显示其工作原理,但是,如果您尝试序列化或存储这些书,价格将不会降低,因为它们不再是属性,而是功能。因此,您必须逆转该过程,即对于每本书:
book.price = ko.unwrap(book.price)

要么
book.price = book.price()

注意:您应该组织代码,以便在将属性转换为可观察对象时很清楚,反之亦然。如果您不仅对price感兴趣,而且对所有属性都感兴趣,则可以使用ko.mapping plugin通过ko.fromJSko.toJS将属性转换为可观察值,反之亦然。

10-07 20:00
查看更多