knockout.js KnockoutJs:可观察数组不更新,只在清理项目时逐项推送

xoshrz7s  于 2022-11-10  发布在  其他
关注(0)|答案(1)|浏览(186)

我有一个knockout组件(在我的magento2项目中),它带有一个observableArray packageItems():

initialize: function (config) {

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

    },

我还有一个函数,它根据packageItem的属性来过滤packageItem。如果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更新。
下面的解决方案是可行的,但是效率非常低,并且在有很多packageItem时速度会很慢。

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);
});
dkqlctbz

dkqlctbz1#

基于上面@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
        });

相关问题