组件渲染优化
组件渲染性能直接影响用户体验,Vue 提供了多种优化手段来减少不必要的渲染开销。
v-show 与 v-if 的选择
JavaScript
// v-if: 真正的条件渲染,切换时销毁/重建
<div v-if="isVisible">内容</div>
// v-show: 始终渲染,仅切换 CSS display
<div v-show="isVisible">内容</div>
| 场景 | 选择 | 原因 |
|---|---|---|
| 频繁切换 | v-show | 避免重复创建销毁 |
| 很少切换 | v-if | 初始渲染开销更小 |
| 条件复杂 | v-if | 支持 else/else-if |
computed 缓存机制
JavaScript
// computed 有缓存,依赖不变不重新计算
const filteredList = computed(() => {
return list.value.filter(item => item.active)
})
// methods 每次调用都会执行
const getFilteredList = () => {
return list.value.filter(item => item.active)
}
优先使用 computed 替代 methods 进行数据计算,避免重复执行。
组件拆分与懒加载
拆分大组件
JavaScript
// 将列表项拆分为独立组件
const ListItem = {
props: ['item'],
template: '<div>{{ item.name }}</div>'
}
// 父组件
const List = {
components: { ListItem },
template: '<list-item v-for="item in items" :key="item.id" :item="item" />'
}
每个 ListItem 独立维护自己的响应式依赖,减少父组件的更新范围。
异步组件
JavaScript
// Vue 2
const AsyncComp = () => import('./HeavyComponent.vue')
// Vue 3
const AsyncComp = defineAsyncComponent(() =>
import('./HeavyComponent.vue')
)
减少响应式数据
JavaScript
import { ref, shallowRef, shallowReactive } from 'vue'
// 不需要响应式的静态数据
const staticConfig = { theme: 'dark', lang: 'zh' }
// 浅响应式,只跟踪第一层
const state = shallowReactive({
list: [{ /* 大数据,不需要深层响应 */ }],
count: 0
})
// ref 的浅版本
const largeData = shallowRef([])
冻结大对象
JavaScript
// Vue 2: Object.freeze 阻止响应式转换
const largeList = Object.freeze([
{ id: 1, name: 'Item 1' },
// ... 1000+ items
])
// Vue 3: markRaw 标记非响应式
import { markRaw } from 'vue'
const rawObj = markRaw({ large: 'data' })
虚拟列表
对于超长列表,使用虚拟滚动只渲染可见区域:
JavaScript
const VirtualList = {
props: ['items', 'itemHeight'],
computed: {
visibleItems() {
const start = Math.floor(this.scrollTop / this.itemHeight)
const end = start + Math.ceil(this.containerHeight / this.itemHeight)
return this.items.slice(start, end + 5)
}
}
}
防抖与节流
JavaScript
// 防抖:搜索输入
const searchQuery = ref('')
const searchResults = ref([])
let timer = null
watch(searchQuery, (val) => {
clearTimeout(timer)
timer = setTimeout(() => {
searchResults.value = fetchData(val)
}, 300)
})
要点总结
- 频繁切换用
v-show,很少切换用v-if - 优先使用
computed利用缓存特性 - 大组件拆分为小组件,减少单次更新范围
- 使用
shallowRef/markRaw减少不必要的响应式开销 - 超长列表使用虚拟滚动只渲染可见区域
- 搜索等高频操作使用防抖/节流
📝 发现内容有误?点击此处直接编辑