2

我正在使用带有延迟更新插件的 knockoutjs 2.0。我有一个旨在对列表进行分页的视图,如下所示:

function PaginatedView(label, items, size) {
    var self = this;

    this.label = ko.observable(label);

    // List of all items to display
    this.list = ko.observableArray(items);

    // List that contains the items on the current page
    this.rows = ko.observableArray([]);

    this.pageSize = ko.observable(size || 5);
    this.pageIndex = ko.observable(0);

    function populateList() {
        var size = self.pageSize();
        var start = self.pageIndex() * size;
        self.rows( self.list.slice(start, start + size) );
        console.log(self.label() + ": Set rows to range", start, start + size - 1);
    }

    // if the deferEvaluation value is true, no items are ever displayed
    ko.computed(populateList, null, {deferEvaluation: false});    

    this.maxPageIndex = ko.computed(function() {
        return Math.ceil(this.list().length / this.pageSize()) - 1;
    }, this);

    this.pageList = ko.computed(function() {
        var pages = [];
        for (var p = 0; p <= self.maxPageIndex(); p++)
            pages.push(p+1);

        return pages;
    });

    this.goToPage = function(p) {
        p--;
        if (p>=0 && p<=self.maxPageIndex())
            self.pageIndex(p);
    }
};

在我的应用程序中,我创建了多个视图,这些视图通过不同的对象列表进行分页。为了跟踪人们实际看到的项目,我想推迟分页的计算(在上面的populateList()函数中),直到视图真正准备好显示。

deferEvaluation我想我可以通过将选项设置为 false 来使用 deferred-updates 插件来实现这一点。但如果我这样做,我根本看不到任何输出。我用 jsfiddle构建了一个小测试用例来说明问题。将该值设置为 false 时,控制台将在选择任何列表之前显示两行输出;将值设置为 true 时,不会显示任何列表元素。

我究竟做错了什么?

4

1 回答 1

2

该行:

ko.computed(populateList, null, {deferEvaluation: false});    

创建一个匿名计算的 observable(因为它没有分配给任何东西)。因为它从未被分配过,所以它不会在任何地方被读取。如果 deferEvaluation 为真,内部函数 (populateList) 不会运行,直到有东西尝试读取计算出的 observable,这当然不会发生!

如果您不使用 deferEvaluation,您仍然会丢弃引用,但是当您定义计算的 observable 时,populateList 会立即被调用。在这种情况下,淘汰依赖跟踪将意识到您的匿名计算 observable 依赖于诸如“pageSize”之类的东西,它还将意识到计算的 observable 更新了“rows”变量,即“rows”依赖于计算的 observable。然后设置足够它可以工作,但这并不理想。

我认为我修复它的方法是:

首先,更改 populateList 函数以返回一个数组:

function populateList() {
    var size = self.pageSize();
    var start = self.pageIndex() * size;
    var result = self.list.slice(start, start + size);
    console.log(self.label() + ": Set rows to range", start, start + size - 1);
    return result;
}

然后调用计算的可观察行:

this.rows = ko.computed(populateList, null, {deferEvaluation: false});   
于 2012-04-13T15:13:05.970 回答