vxe-table性能优化实战:markRaw、shallowRef你真的会用吗?

最近在做一个比较复杂的表格模块,使用的是 vxe-table 方案。
页面初看没什么问题,但当你加载上几百条数据、加上分页、列渲染和虚拟滚动……性能直接告急!

所以,我开始对表格做了一轮 Vue 3 级别的性能优化,从最小的细节下手,比如:

  • 避免没必要的响应式转换
  • 静态化配置项
  • 优化虚拟滚动
  • 使用 shallowRef 和 markRaw

下面我结合代码,一步步讲讲我是怎么做的。

先上结论:一切能静就静,能懒就懒!

初始表格:一不小心就响应了一整个 ECharts

项目中我们用了这样的表格代码:

1
const tableRef = ref<VxeTableInstance>();

这时候问题就来了,ref() 默认是深度响应式,Vue 会尝试递归将对象包一层 Proxy,哪怕它是个组件实例、DOM、甚至一个 ECharts
对象。想象一下,Vue 把整个 ECharts 实例的内部对象都监听了一遍,性能不爆炸才怪!

正确姿势:shallowRef + markRaw

1. 使用 shallowRef:只包最外层,性能 up up up!

1
const tableRef = shallowRef<VxeTableInstance>();

2. 使用 markRaw:彻底免疫响应式!

你可以把一些静态对象(例如 虚拟滚动配置)直接标记为 raw,比如:

1
2
3
4
5
const VIRTUAL_Y_CONFIG = markRaw({
enabled: true,
gt: 15,
oSize: 2,
});

这类配置根本不需要 Vue 响应式处理,反而包一层反而浪费性能,干脆跳过 是最优解。

实战应用在 vxe-table 上

我把所有不变的配置都静态化了,比如:

1
2
3
4
5
6
7
8
9
10
const EDIT_CONFIG = markRaw({
trigger: 'manual',
mode: 'cell',
enabled: false,
});

const SORT_CONFIG = markRaw({
trigger: 'cell',
remote: true,
});

还有一堆配置项我全都 markRaw 了,表格整体立刻丝滑了不少。

进阶优化:优化列渲染

你有没有发现,当你传 columnsvxe-table 的时候,只要数据发生哪怕一点变化,整个渲染就像火山爆发。

所以我用了 computed + markRaw 的组合拳:

1
2
3
4
5
6
7
8
9
10
11
const optimizedColumns = computed(() => {
return props.columns.map((col) =>
markRaw({
...col,
showOverflow: false,
sortable: false,
filters: null,
editRender: null,
}),
);
});

这个 computed 只有在 columns 真正变化时才会重新执行,配合 markRaw,把性能压榨得明明白白。

小细节决定成败:样式层面优化也别放过!

1
2
3
4
.vxe-table * {
transition: none !important;
animation: none !important;
}

全局关闭过渡 + 动画,减少浏览器重绘;同时:

1
2
3
.vxe-body--row {
contain: layout style paint;
}

这是 Chrome 支持的 CSS 优化技巧,防止多余的重排。

总结一句话:

Vue 3 的响应式系统很强,但别滥用,尤其是用在大型组件、配置对象、DOM 实例上。能用 shallowRef 的不要用 ref,能用 markRaw
的别犹豫!