Shopware重写sw-order-list后repository.search为何频繁调用?
问题原因与解决方案
为什么会重复调用repository.search?
你把异步请求放在了**计算属性orderColumns**里,而计算属性是Vue响应式系统的一部分:
- 计算属性会在依赖的响应式数据(比如
this.page、this.limit、this.orders)变更时自动重新执行 - Shopware的订单列表组件会因为分页、状态更新等频繁触发响应式数据变化,导致计算属性反复执行,每次执行都会循环发起新的搜索请求
- 同时你在循环里反复给同一个
criteria添加过滤器,会导致查询条件叠加,请求结果也会出错
正确的实现方式
计算属性应该是纯函数,不能包含异步请求这类副作用。我们需要把数据请求移到专门的方法中,配合缓存机制避免重复请求,同时通过监听订单数据变化触发请求。
修改后的代码示例:
import template from './sw-order-list.html.twig'; const { Component } = Shopware; const { Criteria } = Shopware.Data; Component.override('sw-order-list', { template, data() { return { // 缓存每个客户的订单数量,避免重复请求 customerOrderCounts: {} }; }, computed: { orderColumns() { const columns = this.$super('orderColumns'); columns.push({ property: 'customerOrdersCount', label: 'Test', allowResize: true, sortable: false, align: 'left', // 自定义渲染函数,从缓存中读取数据 renderer: (_, order) => { return this.customerOrderCounts[order.orderCustomer.customerId] || '加载中...'; } }); return columns; }, }, watch: { // 监听订单列表变化,立即且深度监听 orders: { immediate: true, deep: true, handler(newOrders) { this.loadCustomerOrderCounts(newOrders); } } }, methods: { async loadCustomerOrderCounts(orders) { const repository = this.repositoryFactory.create('order_customer'); // 收集需要查询的客户ID并去重 const customerIds = [...new Set(orders.map(order => order.orderCustomer.customerId))]; // 过滤掉已经缓存过的ID,只请求新数据 const uncachedIds = customerIds.filter(id => !this.customerOrderCounts[id]); if (uncachedIds.length === 0) return; // 构建查询条件:一次查询所有未缓存的客户ID,用聚合统计订单数量 const criteria = new Criteria(); criteria.addFilter(Criteria.in('customer.id', uncachedIds)); criteria.addAggregation( Criteria.terms('customerCounts', 'customer.id', null, null, Criteria.count('orderCount')) ); try { const result = await repository.search(criteria); const countBuckets = result.aggregations.customerCounts.buckets; // 更新缓存数据 countBuckets.forEach(bucket => { this.customerOrderCounts[bucket.key] = bucket.orderCount; }); // 处理没有订单的客户,默认显示0 uncachedIds.forEach(id => { if (!this.customerOrderCounts[id]) { this.customerOrderCounts[id] = 0; } }); } catch (error) { console.error('加载客户订单数量失败:', error); // 错误处理:给未加载成功的ID设置默认值 uncachedIds.forEach(id => { this.customerOrderCounts[id] = '加载失败'; }); } } } });
关键优化点
- 缓存机制:用
customerOrderCounts对象缓存每个客户的订单数量,避免重复请求同一客户的数据 - 批量请求:通过
Criteria.in一次查询多个客户ID,减少HTTP请求次数 - 聚合查询:用
count聚合直接获取订单数量,无需返回全量订单数据,提升性能 - 响应式监听:通过
watch监听订单列表变化,自动触发数据加载 - 错误处理:添加try/catch处理请求失败的情况,提升用户体验
内容的提问来源于stack exchange,提问作者DannyDan
相关产品推荐
相关产品推荐

