基本上我有一个 observableArray 并且每个项目的值都不是可观察的。这意味着当我更改项目值时,observableArray 的 foreach 循环中的 UI 不会相应更新。
如果我必须将它们设置为可观察的,这意味着巨大的变化,那么有没有一种方法可以手动刷新 UI 或 observableArray foreach?
基本上我有一个 observableArray 并且每个项目的值都不是可观察的。这意味着当我更改项目值时,observableArray 的 foreach 循环中的 UI 不会相应更新。
如果我必须将它们设置为可观察的,这意味着巨大的变化,那么有没有一种方法可以手动刷新 UI 或 observableArray foreach?
是的,您可以valueHasMutated
为您的数组调用函数:
yourArray.valueHasMutated();
编辑:如果首先没有帮助你可以做'脏'刷新:
self.refresh = function(){
var data = self.array().slice(0);
self.array([]);
self.array(data);
};
这是工作小提琴:http: //jsfiddle.net/vyshniakov/FuEy6/2/
当您有一个带有不可观察元素的可观察数组,并且数组中某个元素的某些属性发生变化时,如果您只想刷新该元素,则可以使用indexOf
and splice
,如下所示:
var changedIdx = obsArray.indexOf(changedItem);
obsArray.splice(changedIdx , 1); // removes the item from the array
obsArray.splice(changedIdx , 0, changedItem); // adds it back
它的作用是在数组中查找元素,将其删除,然后将其插入回去。当它被插入回来时,该元素再次被绑定,具有新的值。
如果您喜欢这个解决方案,您可以扩展所有 ko 可观察数组的功能,如下所示:
ko.observableArray.fn.refresh = function (item) {
var index = this['indexOf'](item);
if (index >= 0) {
this.splice(index, 1);
this.splice(index, 0, item);
}
}
然后,当您更改数组的一项时,您只需进行以下调用:
obsArray.refresh(changedItem);
如果您的数组中有许多元素,您将在dirty
Artem Vyshniakov 的刷新方面获得改进的性能,它会更新数组中所有元素的绑定,而不仅仅是更改的元素。
注意:valueHasMutated
, appart 没有记录(我想是供内部使用),仅检查数组本身是否已更改,而不检查数组中的不可观察元素是否已更改,因此它不起作用。即它只检测您是否已向数组添加元素、从数组中删除元素、使用新的不同元素更改数组元素或更改元素的顺序。但它不检查元素本身是否发生了变化
我最终使用了上面的肮脏方法,但这样做是为了让我所有的可观察数组都具有此功能。
ko.observableArray.fn.refresh = function () {
var data = this().slice(0);
this([]);
this(data);
};
valueHasMutated 对我不起作用。整个列表都必须更新,这有点蹩脚。或者在我的情况下,找到一种方法来扩展 ko 映射插件以用可观察对象填充可观察数组。
我通过替换数组中的整个对象找到了一个简单的解决方案。
在此示例中,参数ix是索引,oLine是更新的对象,oVM.objProps.lines包含数组。该解决方案就像一个冠军。
/* This contortion causes the computed function to fire because
* we have replaced the entire line object.
*/
function forceRefresh(ix,oLine) {
var oVM = pme.getVM();
oLine = JSON.parse(JSON.stringify(oLine));
oVM.oObjProp.lines[ix] = oLine;
}
我正在使用带有 deferUpdates 的 Knockout,而 JotaBe 的解决方案需要更新。
似乎 Knockout 在删除/添加时检测到这是同一个项目,因此不要刷新数组。
我采用了以下解决方案:
ko.observableArray.fn.refresh = function (item, index) {
if (index==null) index = this['indexOf'](item);
if (index >= 0) {
this.splice(index, 1, ko.utils.extend({}, item)) // create new item
//this.splice(index, 1);
//this.splice(index, 0, item);
}
}
它会正确刷新数组!:-)
注意我在 refresh 函数中添加了第二个参数,用于在给出索引时指定索引,以避免运行 indexOf。