我正在尝试解决淘汰赛的问题。我想要做的是拥有一个根模型,其中包含另一个模型的 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 问题?或者也许我做错了?