在Vue3项目中,动态组件频繁切换时会重复创建和销毁实例,导致性能损耗。本文通过几个实际案例,演示如何使用KeepAlive内置组件和手动缓存机制来复用组件实例,提升页面响应速度。
- // 基础示例:KeepAlive包裹动态组件
- <template>
- <div>
- <button @click="current = 'CompA'">显示A</button>
- <button @click="current = 'CompB'">显示B</button>
- <KeepAlive>
- <component :is="current" />
- </KeepAlive>
- </div>
- </template>
- <script setup>
- import { ref } from 'vue'
- import CompA from './CompA.vue'
- import CompB from './CompB.vue'
- const current = ref('CompA')
- </script>
复制代码
<KeepAlive>会将切换隐藏的组件保留在内存中,再次显示时无需重新创建,组件内部状态(如输入框内容)也会被保留。
控制缓存范围:include / exclude
若只想缓存特定组件,可使用include属性,其值可以是组件名称字符串、正则或数组。例如只缓存CompA:
- <KeepAlive include="CompA">
- <component :is="current" />
- </KeepAlive>
复制代码
使用exclude则排除指定组件,其余均被缓存。注意组件名需与注册名称一致(使用<script setup>时默认文件名为组件名)。
限制缓存数量:max属性
当缓存实例过多可能占用内存,max可设置最多缓存实例数,超过时最早缓存的实例会被销毁。
- <KeepAlive max="2">
- <component :is="current" />
- </KeepAlive>
复制代码
若三个组件轮流切换,只缓存最近两个,第三个出现时第一个被销毁。
生命周期钩子:onActivated / onDeactivated
被KeepAlive缓存的组件会触发两个特殊钩子,可用于数据刷新或资源释放。
- // 在CompA.vue中
- import { onActivated, onDeactivated } from 'vue'
- onActivated(() => {
- console.log('CompA被激活(从缓存显示)')
- })
- onDeactivated(() => {
- console.log('CompA被停用(隐藏到缓存)')
- })
复制代码
手动管理组件实例缓存
某些场景需更灵活的控制,可通过对象手动存储组件实例。利用shallowRef和markRaw避免Vue对组件定义做深层响应式处理。
- <template>
- <div>
- <button @click="show('CompA', CompA)">显示A</button>
- <button @click="show('CompB', CompB)">显示B</button>
- <component :is="currentComp" v-if="currentComp" />
- </div>
- </template>
- <script setup>
- import { ref, shallowRef, markRaw } from 'vue'
- import CompA from './CompA.vue'
- import CompB from './CompB.vue'
- const cache = {}
- const currentComp = ref(null)
- function show(name, comp) {
- if (!cache[name]) {
- cache[name] = markRaw(shallowRef(comp))
- }
- currentComp.value = cache[name].value
- }
- </script>
复制代码
同样达到复用实例的效果,但需要手动管理缓存对象和显示逻辑。
封装为组合式函数
将手动缓存逻辑抽离成可复用的useDynamicComponent函数:
- // useDynamicComponent.js
- import { ref, shallowRef, markRaw } from 'vue'
- export function useDynamicComponent() {
- const cache = {}
- const currentComp = ref(null)
- const show = (name, component) => {
- if (!cache[name]) {
- cache[name] = markRaw(shallowRef(component))
- }
- currentComp.value = cache[name].value
- }
- return { currentComp, show }
- }
- </script>
- <script setup>
- // 使用组合式函数
- import { useDynamicComponent } from './useDynamicComponent'
- import CompA from './CompA.vue'
- import CompB from './CompB.vue'
- const { currentComp, show } = useDynamicComponent()
- </script>
复制代码
这样多个组件可以共享同一份缓存逻辑,保持代码整洁。
总结
KeepAlive适用于常规动态组件缓存场景,配置简单;手动实例缓存和组合式函数适合需要精细控制或跨组件复用逻辑的情况。根据实际需求选择合适方式,可有效减少不必要的组件销毁重建,提升Vue3应用性能。 |