You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vue应用中循环内调用的reduce函数运行过慢导致页面冻结如何优化

性能优化方案

1. 优先解决 O(n*m) 级别的最大性能瓶颈

你当前代码中耗时最长的点是 reduce 内部每次遍历行数据时,都调用 Array.find 在 kitsData 中匹配对应数据。如果有12000条行数据、同时 kitsData 也有上千条的话,这部分的时间开销会占到总耗时的90%以上。
优化方式:提前把 kitsData 转换为以 heir_identifier 为key的对象映射表,查找时间直接降到 O(1)。

// 拿到kitsData后立即预处理为映射表,全程只需要执行一次
this.kitsMap = this.kitsData.reduce((map, kit) => {
  map[kit.heir_identifier] = kit
  return map
}, {})

替换reduce内的查找逻辑:

// 原写法,每次都遍历整个kitsData
// const foundKit = vm.$data.kitsData.find((kit) => kit.heir_identifier === sku.heir_id)
// 优化后写法,直接从映射表取
const foundKit = this.kitsMap[sku.heir_id]

仅这一项修改,reduce的执行速度至少可以提升90%。

2. 精简reduce内部的冗余操作

  • 提前把字符串类型的数值转为数字,避免每次运算都做隐式转换
  • 员工的公共属性(area、group、warehouse等)仅在首次创建对象时赋值,不需要每次遍历行数据都重复覆盖
  • 删掉无用的全局status变量赋值,你的代码中status是全局变量,不仅会导致数据错乱,还增加了不必要的操作
    优化后的reduce核心逻辑:
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: row.area, group: row.group_name,
      warehouse: row.warehouse, locale: row.locale
    })
    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: row.itemDate, skus: {}})
    const sku = order.skus[row.sku] || (order.skus[row.sku] = {
      categories: 0, qty: 0, itemDate: row.itemDate, 
      expected: row.shipDate, created: row.created_date, 
      unavailable: 0, available:0, heir_id: row.heir_identifier
    })

    sku.categories += catePerItem
    sku.qty += qty

    employee.total_categories += catePerItem * qty
    employee.total_items += qty

    const foundKit = kitsMap[sku.heir_id]
    if (foundKit) {
      const new_avail = 10
      if(sku.qty > new_avail){
        date.unavailable += 1
        sku.unavailable += 1
      }
    }
    return a
  }, {})

计算属性调用方式修改为传入映射表:

employeeData() {
  return reduceFunction(this.rows, this.kitsMap)
}

3. 优化模板渲染逻辑,删除嵌套循环判断

你当前的模板中,每个日期单元格都要遍历该员工的所有日期数据,再用v-if判断是否匹配当前日期,12000条员工数据+11天日期的场景下,会多出十几万次无效循环。
优化方式:直接通过日期key取对应值,完全删掉嵌套的v-for和v-if:

<div id="app">
  <tr v-for="(value, employee) in employeeData" :key="employee">
    <td>@{{employee}}</td>
    <td v-for="date in dates" :key="date" >
      @{{ value.dates[date]?.total_categories || '' }}
    </td>
  </tr>
</div>

修改后渲染速度可以提升数倍。

4. 超大数据量的额外优化

如果做完上述优化后渲染仍然卡顿,可以引入虚拟滚动组件,仅渲染可视区域内的DOM,不管多少条数据都不会出现卡顿。如果不需要一次性展示所有数据,也可以做分页处理,每页仅渲染几十条数据即可。

内容的提问来源于stack exchange,提问作者Geoff_S

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 10:15:04