Vue项目reduce函数内if/else导致大数据量运行变慢的优化咨询
性能根因分析
你遇到的性能问题核心是vm.$data.kitsData.find(...)这段逻辑的时间复杂度太高:
- 每遍历一条row记录,就会完整遍历一次整个
kitsData数组查找匹配项,假设你的rows有1000条,kitsData有1000条,总执行次数就是100万次,量级上来之后延迟自然会非常明显。 - 把逻辑抽离到reduce结束后执行不会改变O(n*m)的时间复杂度本质,最多只是延迟了计算时间,不能根本解决性能问题。
最优优化方案
提前把kitsData转换为以heir_identifier为键的哈希映射(Map/普通对象均可),查找时间直接从O(m)降到O(1),总时间复杂度降到O(n+m),性能提升最明显,也符合函数式编程的优化思路。
优化后的代码示例
首先修改reduceFunction,把kitsMap作为参数传入,避免直接访问vm实例:
const reduceFunction = (rows, kitsMap) => rows.reduce( (a, row) => { // 提前做一次类型转换,避免重复计算 const catePerItem = Number(row.categories_per_item) const qty = Number(row.qty) const employee = a[row.employee] || (a[row.employee] = {dates: {}, total_categories:0, total_items: 0, area: '', group: ''}) const date = employee.dates[row.itemDate] || (employee.dates[row.itemDate] = {categories: 0, qty: 0, total_categories: 0, unavailable: 0, orders: {}}) date.categories += catePerItem * qty date.qty += qty date.total_categories = date.categories const order = date.orders[row.order_number] || (date.orders[row.order_number] = {itemDate: '', skus: {}}) order.itemDate = row.itemDate; const sku = order.skus[row.sku] || (order.skus[row.sku] = {categories: 0, qty: 0, itemDate: '', expected: '', created: '', unavailable: 0, available:0, status: ''}) sku.categories += catePerItem sku.qty += qty sku.itemDate = row.itemDate sku.expected = row.shipDate sku.created = row.created_date sku.heir_id = row.heir_identifier employee.total_categories += catePerItem * qty employee.total_items += qty employee.area = row.area employee.group = row.group_name employee.warehouse = row.warehouse employee.locale = row.locale // O(1)时间查找,比find快几十上百倍 const foundKit = kitsMap.get(sku.heir_id) const new_avail = 10; if (foundKit) { if(sku.qty > new_avail){ sku.status = "Not available"; date.unavailable += 1 sku.unavailable += 1 }else{ sku.status = "Available" } }else{ sku.status = "No item found" } return a }, {} );
然后修改computed里的调用逻辑,提前构建kitsMap:
computed: { employeeData() { // 只需要遍历一次kitsData构建映射 const kitsMap = new Map(this.kitsData.map(kit => [kit.heir_identifier, kit])) return reduceFunction(this.rows, kitsMap) }, // 其余代码不变 }
额外优化建议
- 原代码里的
status看起来是全局变量,每次循环都会覆盖它的值,如果你不需要这个全局状态,建议把状态存在对应的sku对象里,避免全局变量的额外开销,也不会出现数据覆盖的问题。 - 原代码里sku初始化时
categories、qty设为了空字符串,后续做加法运算会隐式类型转换,建议初始化就设为数字0,避免隐式转换的开销和潜在bug。 - 避免在reduce里直接访问vm的响应式属性,提前把需要的普通值提取出来,减少响应式代理的读取开销。
内容的提问来源于stack exchange,提问作者Geoff_S
相关产品推荐
相关产品推荐

