在 Vue 3 中,如何缓存和复用动态组件

在 Vue 3 中,如何缓存和复用动态组件,这有助于提高应用的性能,避免组件重复创建和销毁带来的开销。下面详细介绍其使用方法和相关配置。

1. 使用 <KeepAlive> 组件缓存动态组件

基本使用

<KeepAlive> 是 Vue 3 内置的一个组件,它可以将包裹在其中的动态组件进行缓存,当组件被切换隐藏时,其状态会被保留,再次显示时无需重新创建。

vue 复制代码
<template>
  <div>
    <button @click="currentComponent = 'ComponentA'">显示组件 A</button>
    <button @click="currentComponent = 'ComponentB'">显示组件 B</button>
    <!-- 使用 KeepAlive 包裹动态组件 -->
    <KeepAlive>
      <component :is="currentComponent" />
    </KeepAlive>
  </div>
</template>

<script setup>
import { ref } from 'vue';
import ComponentA from './ComponentA.vue';
import ComponentB from './ComponentB.vue';

const currentComponent = ref('ComponentA');

const components = {
  ComponentA,
  ComponentB
};
</script>
代码解释
  • 在模板中,使用 <KeepAlive> 组件包裹 <component :is="currentComponent" />,这样 ComponentA 和 ComponentB 在切换时会被缓存。
  • currentComponent 是一个响应式变量,用于控制显示哪个组件。

包含和排除特定组件

你可以使用 include 和 exclude 属性来指定哪些组件需要被缓存或排除。这两个属性的值可以是组件名称的字符串、正则表达式或数组。

vue 复制代码
<template>
  <div>
    <button @click="currentComponent = 'ComponentA'">显示组件 A</button>
    <button @click="currentComponent = 'ComponentB'">显示组件 B</button>
    <!-- 只缓存 ComponentA -->
    <KeepAlive include="ComponentA">
      <component :is="currentComponent" />
    </KeepAlive>
  </div>
</template>

<script setup>
import { ref } from 'vue';
import ComponentA from './ComponentA.vue';
import ComponentB from './ComponentB.vue';

const currentComponent = ref('ComponentA');

const components = {
  ComponentA,
  ComponentB
};
</script>
代码解释
  • include="ComponentA" 表示只有 ComponentA 会被缓存,ComponentB 不会被缓存,每次切换到 ComponentB 时都会重新创建。
  • 若使用 exclude 属性,则与之相反,被排除的组件不会被缓存。例如 <KeepAlive exclude="ComponentB"> 会缓存除 ComponentB 之外的组件。

最大缓存实例数

你可以使用 max 属性来限制 <KeepAlive> 缓存的最大实例数量。当缓存的实例数量超过 max 值时,最早缓存的实例会被销毁。

vue 复制代码
<template>
  <div>
    <button @click="currentComponent = 'ComponentA'">显示组件 A</button>
    <button @click="currentComponent = 'ComponentB'">显示组件 B</button>
    <button @click="currentComponent = 'ComponentC'">显示组件 C</button>
    <!-- 最多缓存 2 个组件实例 -->
    <KeepAlive max="2">
      <component :is="currentComponent" />
    </KeepAlive>
  </div>
</template>

<script setup>
import { ref } from 'vue';
import ComponentA from './ComponentA.vue';
import ComponentB from './ComponentB.vue';
import ComponentC from './ComponentC.vue';

const currentComponent = ref('ComponentA');

const components = {
  ComponentA,
  ComponentB,
  ComponentC
};
</script>
代码解释
  • max="2" 表示 <KeepAlive> 最多缓存 2 个组件实例。当切换到第三个组件时,最早缓存的组件实例会被销毁。

组件缓存状态的生命周期钩子

当组件被 <KeepAlive> 缓存时,会有两个特殊的生命周期钩子 onActivated 和 onDeactivated,可以在这两个钩子中执行相应的逻辑。

vue 复制代码
<template>
  <div>
    This is Component A.
  </div>
</template>

<script setup>
import { onActivated, onDeactivated } from 'vue';

onActivated(() => {
  console.log('Component A is activated.');
});

onDeactivated(() => {
  console.log('Component A is deactivated.');
});
</script>
代码解释
  • onActivated:当组件被激活(从缓存中显示出来)时触发。
  • onDeactivated:当组件被停用(被隐藏并放入缓存)时触发。

通过上述方法,你可以在 Vue 3 中灵活地缓存和复用动态组件,提高应用的性能和用户体验。

2. 组件实例缓存(手动管理)

除了使用 <KeepAlive>,你还可以手动管理组件实例的缓存。通过一个对象来存储组件实例,在需要使用时从对象中获取。

vue 复制代码
<template>
  <div>
    <button @click="showComponent('ComponentA')">显示组件 A</button>
    <button @click="showComponent('ComponentB')">显示组件 B</button>
    <component :is="currentComponent" v-if="currentComponent" />
  </div>
</template>

<script setup>
import { ref, shallowRef, markRaw } from 'vue';
import ComponentA from './ComponentA.vue';
import ComponentB from './ComponentB.vue';

// 存储组件实例的缓存对象
const componentCache = {};
const currentComponent = ref(null);

const showComponent = (name) => {
  if (!componentCache[name]) {
    const component = name === 'ComponentA' ? ComponentA : ComponentB;
    // 创建组件实例并存储到缓存中
    componentCache[name] = markRaw(shallowRef(component));
  }
  currentComponent.value = componentCache[name].value;
};
</script>
代码解释
  • componentCache 是一个对象,用于存储组件实例。
  • showComponent 方法根据传入的组件名称,检查缓存中是否存在该组件实例。如果不存在,则创建实例并存储到缓存中;如果存在,则直接从缓存中获取。

3. 组合式函数封装

可以将动态组件的逻辑封装到组合式函数中,提高代码的复用性。

javascript 复制代码
// useDynamicComponent.js
import { ref, shallowRef, markRaw } from 'vue';

export function useDynamicComponent() {
  const componentCache = {};
  const currentComponent = ref(null);

  const showComponent = (name, component) => {
    if (!componentCache[name]) {
      componentCache[name] = markRaw(shallowRef(component));
    }
    currentComponent.value = componentCache[name].value;
  };

  return {
    currentComponent,
    showComponent
  };
}
vue 复制代码
<template>
  <div>
    <button @click="showComponent('ComponentA', ComponentA)">显示组件 A</button>
    <button @click="showComponent('ComponentB', ComponentB)">显示组件 B</button>
    <component :is="currentComponent" v-if="currentComponent" />
  </div>
</template>

<script setup>
import { useDynamicComponent } from './useDynamicComponent.js';
import ComponentA from './ComponentA.vue';
import ComponentB from './ComponentB.vue';

const { currentComponent, showComponent } = useDynamicComponent();
</script>
代码解释
  • useDynamicComponent 组合式函数封装了动态组件的缓存和显示逻辑。
  • 在组件中使用该组合式函数,通过调用 showComponent 方法来显示不同的组件。
相关推荐
lovingsoft4 分钟前
Chrome Lighthouse 详解
前端·chrome
Qlly14 分钟前
全栈工程师怎么接需求?从一句「加个功能」聊到能开发、能验收
前端·后端
马可家的菠萝18 分钟前
你的微信“文件传输助手”,是不是已经成了第二个网盘?
前端·后端·架构
略略略啦18 分钟前
Vibe Coding 基于Spec DD和TDD的实践指南
前端
shmily麻瓜小菜鸡39 分钟前
前端实现图片与PDF文字识别敏感信息打码方案
前端·pdf·状态模式
石小千44 分钟前
Redis开启ACL认证
数据库·redis·缓存
打工仔折腾 AI1 小时前
LangChain 工具调用实战:从 Tool 定义到 Agent 执行链路拆解
java·前端·人工智能·后端·python·langchain·ai agent 实战
汉堡大王95271 小时前
单次输出拉到100万Token:拆完 Gemini 4 Argon 的续写协议,才看懂谷歌这7个月在憋什么
前端·人工智能·后端
看浪的路人1 小时前
第9讲:大模型应用监控与可观测性——OpenTelemetry + Prometheus + Grafana 全链路追踪
java·前端·spring
内存过载1 小时前
用表格模拟甘特图:项目排期的土办法
前端·低代码