31

基本上我有一个 observableArray 并且每个项目的值都不是可观察的。这意味着当我更改项目值时,observableArray 的 foreach 循环中的 UI 不会相应更新。

如果我必须将它们设置为可观察的,这意味着巨大的变化,那么有没有一种方法可以手动刷新 UI 或 observableArray foreach?

4

5 回答 5

59

是的,您可以valueHasMutated为您的数组调用函数:

yourArray.valueHasMutated();

编辑:如果首先没有帮助你可以做'脏'刷新:

self.refresh = function(){
    var data = self.array().slice(0);
    self.array([]);
    self.array(data);
};

这是工作小提琴:http: //jsfiddle.net/vyshniakov/FuEy6/2/

于 2012-11-05T12:05:51.497 回答
21

当您有一个带有不可观察元素的可观察数组,并且数组中某个元素的某些属性发生变化时,如果您只想刷新该元素,则可以使用indexOfand 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);

如果您的数组中有许多元素,您将在dirtyArtem Vyshniakov 的刷新方面获得改进的性能,它会更新数组中所有元素的绑定,而不仅仅是更改的元素。

注意:valueHasMutated, appart 没有记录(我想是供内部使用),仅检查数组本身是否已更改,而不检查数组中的不可观察元素是否已更改,因此它不起作用。即它只检测您是否已向数组添加元素、从数组中删除元素、使用新的不同元素更改数组元素或更改元素的顺序。但它不检查元素本身是否发生了变化

于 2015-01-26T13:11:09.407 回答
5

我最终使用了上面的肮脏方法,但这样做是为了让我所有的可观察数组都具有此功能。

ko.observableArray.fn.refresh = function () {
        var data = this().slice(0);
        this([]);
        this(data);
    };

valueHasMutated 对我不起作用。整个列表都必须更新,这有点蹩脚。或者在我的情况下,找到一种方法来扩展 ko 映射插件以用可观察对象填充可观察数组。

于 2013-09-22T19:49:10.380 回答
0

我通过替换数组中的整个对象找到了一个简单的解决方案。

在此示例中,参数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;
}
于 2017-10-26T08:05:09.963 回答
0

我正在使用带有 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。

于 2018-05-22T13:52:36.883 回答