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、表单切换、编辑/预览模式等
相关推荐
行云流水6263 小时前
uniapp pinia实现数据持久化插件
前端·javascript·uni-app
zhangyao9403303 小时前
uniapp动态修改 顶部导航栏标题和右侧按钮权限显示隐藏
前端·javascript·uni-app
福尔摩斯张5 小时前
Axios源码深度解析:前端请求库设计精髓
c语言·开发语言·前端·数据结构·游戏·排序算法
aiguangyuan5 小时前
React 中什么是可中断更新?
javascript·react·前端开发
李牧九丶5 小时前
从零学算法1334
前端·算法
1***s6326 小时前
JavaScript微服务
javascript·微服务·devops
周周爱喝粥呀6 小时前
UI设计原则和Nielsen 的 10 条可用性原则
前端·ui
小云朵爱编程6 小时前
Vue项目Iconify的使用以及自定义图标,封装图标选择器
前端·javascript·vue.js
前端大卫6 小时前
CSS 属性值 initial、unset 和 revert 的解析
前端