KnockoutJs:可观察数组不更新,仅在逐个清除和推送项目时更新

KnockoutJs: observable array does not update, only when clearing and pushing items one-by-one

我有一个带有 observableArray packageItems() 的淘汰组件(在我的 magento2 项目中):

    initialize: function (config) {

        this.packageItems = ko.observableArray([]);

    },

我还有一个根据属性过滤 packageItems 的功能。如果 packageitem 通过过滤器可见,则过滤器设置显示的 packageItem.is_visible 槽:

<div class="pp-grid-item" data-bind="visible:is_visible">
..
</div>

呼叫方:

<section class="pp-grid-container" data-bind="foreach: packageItems()" >
<!-- ko template: { name: 'Company_PackageModule/Item/' + $parent.renderer_template_item } -->
<!-- /ko -->
</section>

我尝试以这种方式更新 observableArray:

this.packageItems().forEach((packageItem, index) => {
    packageItem =  this.applyFilters(packageItem);
    this.packageItems()[index].is_visible =  packageItem.is_visible;
});
this.packageItems.valueHasMutated();

但这不会触发 DOM 的变化。

我也试过:

this.packageItems().forEach((packageItem, index) => {
    packageItem =  this.applyFilters(packageItem); // this sets is_visible
    this.packageItems.splice(index, 1, packageItem);
    console.log('Splicing packageitems on '+index+' for one with visibility '+packageItem.is_visible);
});

这会将以下内容记录到控制台:

Splicing packageitems on 0 for one with visibility true
Splicing packageitems on 1 for one with visibility true
Splicing packageitems on 2 for one with visibility false
Splicing packageitems on 3 for one with visibility false
Splicing packageitems on 4 for one with visibility false
Splicing packageitems on 5 for one with visibility true
Splicing packageitems on 6 for one with visibility true
Splicing packageitems on 7 for one with visibility true

这意味着它在做正确的事情,除了更新模板。

我还在拼接后添加了一个 console.log(this.packageItems()),它显示了包含更新项的正确数组,但没有 dom 更新。

以下解决方案有效,但效率很低,而且当有很多 packageItems 时会变慢。

let currentPackageItems = new Array;
this.packageItems().forEach((packageItem, index) => {
    packageItem = this.applyFilters(packageItem);
    currentPackageItems.push(packageItem);
});
this.packageItems.removeAll();
currentPackageItems.forEach((newPackageItem, index) => {
    this.packageItems.push(newPackageItem);
});

基于上面@Nathaniel Flick 的回答。我通过使每个 packageItem 的 is_visible 属性可观察来修复它:

    addToPackageItems: function (row) {
        row.is_visible = ko.observable(row.is_visible);
        row = this.applyFilters(row);
        this.packageItems.push(row);
    },

在过滤函数中,只需要这个:

       this.packageItems().forEach((packageItem, index) => {
            this.applyFilters(packageItem); //sets packageItem.is_visible
        });