用 代码 + 编译结果 把差异讲透。
1. Vue2 的优先级:v-for 先于 v-if
1.1 源码层面
Vue2 的模板编译器在解析 AST 时,会把 v-for
节点标记为 父节点 ,v-if
标记为 子节点 (或同级节点),因此 循环先执行,条件判断后执行。
1.2 编译结果
vue
<template>
<div v-for="i in 100" v-if="i % 2 === 0">{{ i }}</div>
</template>
编译后(简化伪码):
js
_render() {
return _l(100, i => i % 2 === 0 ? _c('div', i) : null);
}
_l
是v-for
渲染函数,先循环 100 次 ,再逐条判断i % 2
。- 后果 :
- 生成 100 个虚拟 DOM 节点,其中 50 个
null
被丢弃。 - 多余计算 、内存浪费 、首屏白屏时间变长。
- 生成 100 个虚拟 DOM 节点,其中 50 个
2. Vue3 的优先级:v-if 先于 v-for
2.1 编译结果
Vue3 模板编译器把 v-if
提升到 父级节点 ,v-for
退到 子级节点。
上例编译后:
js
_render() {
return (_l(
(100).filter(i => i % 2 === 0), // 先过滤
i => _c('div', i)
));
}
- 先过滤再循环,只生成 50 个有效节点。
- 零多余计算,直接渲染正确结果。
3. 差异后果总结
- Vue2:先循环后判断 → 渲染多余节点 → 性能下降。
- Vue3:先判断后循环 → 零浪费 → 性能提升。
4. 最佳实践
- Vue2 :用
computed
提前过滤,避免性能陷阱。 - Vue3 :直接写即可,无需额外处理。