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
});
我有一个带有 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
});