Я пытаюсь решить проблему с нокаутом. То, что я пытаюсь сделать, это иметь корневую модель, содержащую наблюдаемый массив другой модели. Эта модель также содержит наблюдаемый массив одной последней модели (называемой «результат»). В зависимости от взаимодействия пользователя первый наблюдаемый массив может быть полностью изменен (сброс массива и добавление других моделей).Нокаут - Обновление наблюдаемого массива моделей
Список предоставлен пользователю, и он может фильтровать результаты с помощью текстового поля (я использую вычисление для фильтрации).
Проблема, с которой я столкнулся, заключается в том, что даже если я сброшу наблюдаемый массив, кажется, что ссылки хранятся на вложенных моделях, а нокаут продолжает возбуждать события на этих моделях, что приводит к тому, что все больше и больше вызовов 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 вызова каждый раз, когда вы нажимаете кнопку.
(мои реальные модели гораздо сложнее. Например, результат содержит гораздо больше свойств)
Что я с моими реальными моделями IE8 говорит мне, что сценарий замедляется IE. И я подозреваю, что это и есть причина. Даже если это не так, я хотел бы знать, почему я получаю такое поведение. Может быть, это больше проблема с Javascript, чем проблема с нокаутом? Или, может быть, я делаю это неправильно?