0

我正在尝试解决淘汰赛的问题。我想要做的是拥有一个根模型,其中包含另一个模型的 observableArray。该模型还包含最后一个模型的 observableArray(称为“结果”)。根据用户交互,第一个 observableArray 可以完全更改(重置数组并添加其他模型)。

向用户呈现一个列表,他可以使用文本字段过滤结果(我正在使用计算过滤)。

我面临的问题是,即使我重置 observableArray,似乎仍然保留对嵌套模型的引用,并且淘汰赛继续在这些模型上触发事件,这导致随着用户更改越来越多的 Javascript 调用列表。

我写了一个小的 jsfiddle 来说明我的意思:http: //jsfiddle.net/PNzM5/ 这是 javascript 代码:

ko.observableArray.fn.pushAll = function (valuesToPush) {
    var underlyingArray = this();
    this.valueWillMutate();
    ko.utils.arrayPushAll(underlyingArray, valuesToPush);
    this.valueHasMutated();
    return this;
};

function Result(value) {
    this.value = ko.observable(value);
}

function NestedItem(name, currentValue) {
    var _this = this;
    this.currentValue = currentValue;
    this.name = ko.observable(name);
    this.totalResults = ko.observableArray([]);
    this.filteredResults = ko.computed(function () {
        console.log('get called by ' + _this.name());
        return ko.utils.arrayFilter(_this.totalResults(), function (result) {
            return result.value().toLowerCase().indexOf(_this.currentValue()) != -1;
        });
    });
}

function Model() {
    var _this = this;
    this.nestedItemList = ko.observableArray([]);
    this.currentValue = ko.observable("");

    this.createFirstList = function () {
        this.nestedItemList([]);
        _this.createItem("sublist 1", [new Result("value 1"), new Result("value 2"), new Result("value 3")]);
        _this.createItem("sublist 2", [new Result("value 4"), new Result("value 5"), new Result("value 6")]);
    }

    this.createSecondList = function () {
        this.nestedItemList([]);
        _this.createItem("sublist 3", [new Result("value 1"), new Result("value 2"), new Result("value 3")]);
        _this.createItem("sublist 4", [new Result("value 4"), new Result("value 5"), new Result("value 6")]);
    }

    this.createItem = function (name, values) {
        var item = new NestedItem(name, _this.currentValue);
        item.totalResults.pushAll(values);
        this.nestedItemList.push(item);
    }
}

和相关的HTML:

<input data-bind="value:currentValue,valueUpdate: 'keyup'" type="text" placeholder="Type to filter"/>
<ul data-bind="foreach: nestedItemList">
    <li class="sublist" data-bind="text: name"></li>
    <!-- ko foreach: filteredResults -->
    <li class="result" data-bind="text: value"></li>
    <!-- /ko -->
</ul>
<button data-bind="event: {click: createFirstList}">First list</button>
<button data-bind="event: {click: createSecondList}">Second list</button>

我记录了对计算到控制台的调用。如果您单击“第一个列表”并尝试过滤结果,您将看到对于您键入的每个字符,将为每个列表调用计算(这很好)。然后,如果您单击“第二个列表”并尝试过滤 agin,您将看到计算将被调用 4 次。每次单击按钮时,您都会多打 2 个电话。

(我的真实模型要复杂得多。例如, Result 包含更多属性)

我用我的真实模型得到的是 IE8 告诉我一个脚本正在减慢 IE。我怀疑这就是原因。即使不是,我也想知道为什么会出现这种行为。也许这比 Knockout 问题更像是一个 Javascript 问题?或者也许我做错了?

4

1 回答 1

0

好的,我找到了解决方案。在“NestedItem”中,我创建了一个重置​​函数,将结果设置为一个空数组:

this.reset = function() {
    _this.totalResults([]);
}

我还在根模型中创建了一个重置​​函数,每次创建新列表时都会调用它:

this.reset = function() {
    ko.utils.arrayForEach(_this.nestedItemList(), function(list) {
        list.reset();
    });
    this.nestedItemList([]);
}

所以,模型现在是:

ko.observableArray.fn.pushAll = function(valuesToPush) {
    var underlyingArray = this();
    this.valueWillMutate();
    ko.utils.arrayPushAll(underlyingArray, valuesToPush);
    this.valueHasMutated();
    return this;
};

function Result(value) {
    this.value = ko.observable(value);
}

function NestedItem(name, currentValue) {
    var _this = this;
    this.currentValue = currentValue;
    this.name = ko.observable(name);
    this.totalResults = ko.observableArray([]);
    this.filteredResults = ko.computed(function() {
        console.log('get called by ' + _this.name());
        return ko.utils.arrayFilter(_this.totalResults(), function(result) {
            return result.value().toLowerCase().indexOf(_this.currentValue()) != -1 ;
        });
    });
    this.reset = function() {
        _this.totalResults([]);
    }
}

function Model() {
    var _this = this;
    this.nestedItemList = ko.observableArray([]);
    this.currentValue = ko.observable("");

    this.createFirstList = function() {
        _this.reset();
        _this.createItem("sublist 1 title", [new Result("value 1"), new Result("value 2"), new Result("value 3")]);
        _this.createItem("sublist 2 title", [new Result("value 4"), new Result("value 5"), new Result("value 6")]);
    }

    this.createSecondList = function() {
        _this.reset();
        _this.createItem("sublist 3 title", [new Result("value 1"), new Result("value 2"), new Result("value 3")]);
        _this.createItem("sublist 4 title", [new Result("value 4"), new Result("value 5"), new Result("value 6")]);
    }

    this.reset = function() {
        ko.utils.arrayForEach(_this.nestedItemList(), function(list) {
            list.reset();
        });
        this.nestedItemList([]);
    }

    this.createItem = function(name, values) {
        var item = new NestedItem(name, _this.currentValue);
        item.totalResults.pushAll(values);
        this.nestedItemList.push(item);        
    }
}

我还减少了我真正的“结果”模型中的可观察对象的数量(我有很多可观察对象,其中一些不需要是可观察对象。简单的属性就足够了。我不再收到 IE 错误对话框。但是,我认为我的解决方案有点hacky。如果有人有更好的解决方案,我会很高兴看到它。:)

编辑:我忘记了 jsfiddle:http: //jsfiddle.net/PNzM5/2/

于 2013-06-13T08:21:59.580 回答