Vue 3 动态组件详解

一、什么是动态组件?

在 Vue 中,动态组件 指的是:

在同一个挂载点(<component> 标签)上,根据条件动态切换不同的组件。

👉 简单来说:

你可以在同一个位置,动态地渲染不同的组件,而不需要手动写一堆 v-if / v-show


二、基本语法

Vue 提供了一个内置组件:

html 复制代码
<component :is="componentName"></component>

语法说明:

  • :is 属性绑定一个组件的名称组件对象

  • 当绑定值变化时,Vue 会自动卸载旧组件渲染新组件


三、示例:最基本的动态组件

html 复制代码
<template>
  <div>
    <button @click="current = 'A'">显示 A 组件</button>
    <button @click="current = 'B'">显示 B 组件</button>
    <component :is="current"></component>
  </div>
</template>

<script setup>
import A from './A.vue'
import B from './B.vue'

const current = ref('A')
</script>
html 复制代码
<!-- A.vue --> 
<template><div>这是组件 A</div></template>
html 复制代码
<!-- B.vue --> 
<template><div>这是组件 B</div></template>

运行后点击按钮,就可以在同一位置来回切换组件 A 和 B。


四、使用组件对象而不是名称

你也可以直接传组件对象:

html 复制代码
<template>
  <div>
    <button @click="current = CompA">A</button>
    <button @click="current = CompB">B</button>
    <component :is="current" />
  </div>
</template>

<script setup>
import CompA from './A.vue'
import CompB from './B.vue'

const current = ref(CompA)
</script>

这种写法在 setup 语法糖 + script setup 环境下更推荐,

因为此时没有全局组件注册的依赖。


五、动态组件的缓存:<keep-alive>

默认情况下,当你切换组件时:

  • 旧组件会被销毁;

  • 新组件会重新创建。

如果你希望切换回来时保留组件的状态(如输入框内容、滚动位置等),

可以使用 <keep-alive>

html 复制代码
<template>
  <keep-alive>
    <component :is="current" />
  </keep-alive>

  <button @click="current = CompA">A</button>
  <button @click="current = CompB">B</button>
</template>

keep-alive 特性:

  • 缓存曾经加载过的组件;

  • 不会重新渲染;

  • 提供生命周期钩子:

    • activated() --- 被激活时触发;

    • deactivated() --- 被切换走时触发。

html 复制代码
export default {
  activated() { console.log('组件被激活') },
  deactivated() { console.log('组件被缓存') }
}

六、实际应用场景

场景 说明
Tab 页切换 每个 Tab 是不同的组件,切换时动态渲染
多表单类型页面 不同类型的表单结构不同,用动态组件加载
组件预览/编辑模式切换 同一位置显示不同的组件视图(如预览/编辑)
插件式架构 根据配置动态加载不同的功能模块

七、示例:Tabs 动态组件应用

html 复制代码
<template>
  <div>
    <button v-for="tab in tabs" :key="tab.name" @click="current = tab.component">
      {{ tab.label }}
    </button>

    <keep-alive>
      <component :is="current" />
    </keep-alive>
  </div>
</template>

<script setup>
import TabHome from './TabHome.vue'
import TabProfile from './TabProfile.vue'
import TabSettings from './TabSettings.vue'

const tabs = [
  { name: 'home', label: '首页', component: TabHome },
  { name: 'profile', label: '资料', component: TabProfile },
  { name: 'settings', label: '设置', component: TabSettings }
]

const current = ref(TabHome)
</script>

八、动态组件的高级用法

1️⃣ 动态加载(懒加载组件)

结合 defineAsyncComponent 使用:

html 复制代码
<script setup>
import { defineAsyncComponent, ref } from 'vue'

const AsyncComp = defineAsyncComponent(() => import('./MyComponent.vue'))
const current = ref(AsyncComp)
</script>

2️⃣ 动态参数传递

可以像普通组件一样绑定 props:

html 复制代码
<component :is="current" :data="someData" @click="handleClick" />

3️⃣ 动态路由结合使用

在 Vue Router 中配合 <router-view>,本质上也是动态组件机制:

html 复制代码
<router-view></router-view>

九、注意事项 ⚠️

注意点 说明
:is 绑定的值必须合法(组件名或组件对象) 否则 Vue 会渲染空标签
<keep-alive> 仅缓存动态组件 不能用于普通的 v-if 切换
组件切换会触发卸载/挂载 注意副作用(比如定时器)需要清理
异步组件需配合加载状态 可搭配 <Suspense>

🔟 总结

功能 描述
<component :is=""> 动态渲染不同组件
<keep-alive> 缓存组件实例
activated/deactivated 生命周期钩子
defineAsyncComponent 异步加载组件
常见场景 Tabs、表单切换、编辑/预览模式等
相关推荐
橙子家14 小时前
浏览器缓存之【结构化数据库与缓存】: IndexedDB、Cache storage 和 Storage buckets
前端
user205855615181314 小时前
X6 中边悬浮置顶,规避 `mouseleave` 事件丢失问题
前端
李明卫杭州14 小时前
CSS aspect-ratio 属性完全指南
前端
Pedantic16 小时前
SwiftUI 手势层级(Gesture Hierarchy)详解
前端
飘尘17 小时前
前端转型全栈(Java后端)的快速上手指引
前端·后端·全栈
一颗烂土豆17 小时前
Meshopt 压缩深度解析,为什么它比 Draco 更快
前端·javascript·webgl
浏览器工程师18 小时前
AI Agent 接浏览器任务,先别让它一路点到底
前端·后端
雨季mo浅忆18 小时前
VSCode自动格式化三要素
前端
爱勇宝19 小时前
深扒 Anthropic 1680 位工程师简历:应届生几乎没机会,AI 公司最缺的不是博士
前端·后端·程序员