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、表单切换、编辑/预览模式等
相关推荐
陈随易5 分钟前
农村程序员聊五险一金
前端·后端·程序员
恋猫de小郭7 分钟前
Swift 6.3 正式发布支持 Android ,它能在跨平台发挥什么优势?
android·前端·flutter
xujing_0610 分钟前
跑马灯组件vue3+es6
前端·javascript·es6
小小善后师21 分钟前
告别周报烦恼:我用 200 行代码打造了一个 AI 工时助手
前端
我只是来分享的21 分钟前
Js也能写外挂?8 行代码改掉《植物大战僵尸》的阳光值!对于js来说超越调用大漠超越调用memory.js
javascript
Mahut24 分钟前
我们是怎么用 TanStack 全家桶的
前端·javascript·架构
FreeBuf_29 分钟前
Claude浏览器扩展漏洞允许通过任意网站实现零点击XSS提示注入
前端·网络·xss
AlunYegeer31 分钟前
【JAVA】网关的管理原理和微服务的Interceptor区分
java·服务器·前端
sensen_kiss35 分钟前
CAN302 电子商务技术 Pt.2 深入了解HTML和CSS
前端·css·学习·html
说实话起个名字真难啊44 分钟前
前端JS审计:渗透测试的“破局之钥”
开发语言·前端·javascript·测试工具