一、什么是动态组件?
在 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、表单切换、编辑/预览模式等 |