Demo)
实现 Tab 切换面板动态组件Demo在 Vue 中动态组件component :is...非常适合实现 Tab 切换面板——根据当前选中的 Tab动态渲染对应的组件且组件实例会被复用或销毁取决于是否使用KeepAlive。下面是一个完整的 Vue 3 单文件组件 Demo包含 Tab 导航和内容区域并演示了组件切换、状态保持和 Props 传递。1. 最终效果预览顶部显示三个 Tab 标签首页、列表、设置。点击 Tab 切换下方内容区域动态渲染对应组件。每个 Tab 组件拥有独立的内部状态如输入框内容切换回去后状态保留使用KeepAlive。2. 完整代码TabPanelDemo.vuetemplate div classtab-demo !-- Tab 导航栏 -- div classtab-nav div v-fortab in tabs :keytab.name classtab-item :class{ active: currentTab tab.name } clickcurrentTab tab.name {{ tab.label }} /div /div !-- 动态组件内容区带 KeepAlive 缓存 -- div classtab-content KeepAlive component :iscurrentComponent :usercurrentUser updatehandleUpdate / /KeepAlive /div !-- 显示当前激活的 Tab 名称调试用 -- p stylemargin-top: 16px; color: #888; 当前激活 Tab{{ currentTab }} /p /div /template script setup import { ref, computed } from vue // ----- 1. 定义 Tab 组件内联方式 ----- // 实际项目中可单独抽离为独立 .vue 文件 const TabHome { name: TabHome, template: div h3 首页/h3 p欢迎来到首页/p input v-modelinputValue placeholder输入一些内容... / p输入内容{{ inputValue }}/p /div , setup() { const inputValue ref() return { inputValue } } } const TabList { name: TabList, template: div h3 列表/h3 ul li v-foritem in items :keyitem.id{{ item.name }}/li /ul button clickaddItem添加项/button /div , setup() { const items ref([ { id: 1, name: Vue.js }, { id: 2, name: React }, { id: 3, name: Angular } ]) const addItem () { const newId items.value.length 1 items.value.push({ id: newId, name: 新项 ${newId} }) } return { items, addItem } } } const TabSettings { name: TabSettings, props: [user], template: div h3⚙️ 设置/h3 p当前用户{{ user?.name || 未登录 }}/p labelinput typecheckbox v-modeldarkMode / 启用暗黑模式/label p暗黑模式{{ darkMode ? 开启 : 关闭 }}/p /div , setup() { const darkMode ref(false) return { darkMode } } } // ----- 2. Tab 配置 ----- const tabs [ { name: home, label: 首页, component: TabHome }, { name: list, label: 列表, component: TabList }, { name: settings, label: 设置, component: TabSettings } ] // 当前激活的 Tab 名 const currentTab ref(home) // 计算当前要渲染的组件 const currentComponent computed(() { const found tabs.find(tab tab.name currentTab.value) return found ? found.component : null }) // 模拟父组件传递给 Tab 的 Props const currentUser ref({ name: 张三, role: admin }) // 监听子组件事件 const handleUpdate (payload) { console.log(收到子组件更新事件, payload) } /script style scoped .tab-demo { max-width: 600px; margin: 0 auto; font-family: Arial, sans-serif; } .tab-nav { display: flex; gap: 4px; border-bottom: 2px solid #e8e8e8; } .tab-item { padding: 10px 20px; cursor: pointer; border-radius: 6px 6px 0 0; transition: background 0.2s; user-select: none; } .tab-item:hover { background: #f0f0f0; } .tab-item.active { background: #1890ff; color: white; font-weight: bold; } .tab-content { padding: 20px; border: 1px solid #e8e8e8; border-top: none; border-radius: 0 0 6px 6px; min-height: 200px; } /style3. 关键点解析核心概念代码实现说明动态组件component :iscurrentComponent /currentComponent是一个组件对象或注册名Vue 会根据它的变化动态渲染不同组件。Tab 切换点击.tab-item更新currentTab再通过computed计算currentComponent。使用v-for遍历tabs数组维护currentTab响应式状态。组件状态保持使用KeepAlive包裹component。不加KeepAlive时每次切换都会销毁旧组件并创建新组件内部状态如输入框内容会丢失。加上后组件实例被缓存状态得以保留。Props 传递:usercurrentUser绑定到动态组件。只要currentComponent对应的组件声明了props就会正常接收。自定义事件updatehandleUpdate子组件可通过emit(update, data)向父组件通信适用于任何动态组件。内联组件定义使用defineComponent或直接对象在父文件中定义。实际项目推荐将 Tab 组件抽离为独立.vue文件便于维护。4. 运行效果说明点击首页→ 显示输入框输入内容后切换到其他 Tab再切回首页输入内容依然存在KeepAlive生效。点击列表→ 显示列表和“添加项”按钮点击添加新项切换后列表状态保留。点击设置→ 显示当前用户从父组件传递和暗黑模式开关状态独立。5. 与路由的区别动态组件适合同一页面内的局部切换如设置面板、仪表盘。Vue Router适合不同页面的切换且拥有独立的 URL 和生命周期钩子。7. 注意事项如果 Tab 组件之间需要独立的缓存策略可以给KeepAlive添加include/exclude属性。动态组件的:is可以传组件对象如TabHome或组件名字符串但在script setup中使用对象更直接。当currentComponent为null时component不渲染任何内容可用于占位或错误处理。