当前位置: 首页 > news >正文

实现 Tab 切换面板(动态组件)Demo

实现 Tab 切换面板(动态组件)Demo

在 Vue 中,动态组件<component :is="...">)非常适合实现 Tab 切换面板——根据当前选中的 Tab,动态渲染对应的组件,且组件实例会被复用或销毁(取决于是否使用<KeepAlive>)。

下面是一个完整的 Vue 3 单文件组件 Demo,包含 Tab 导航和内容区域,并演示了组件切换、状态保持和 Props 传递。


1. 最终效果预览
  • 顶部显示三个 Tab 标签:首页列表设置
  • 点击 Tab 切换下方内容区域,动态渲染对应组件。
  • 每个 Tab 组件拥有独立的内部状态(如输入框内容),切换回去后状态保留(使用<KeepAlive>)。

2. 完整代码(TabPanelDemo.vue
<template> <div class="tab-demo"> <!-- Tab 导航栏 --> <div class="tab-nav"> <div v-for="tab in tabs" :key="tab.name" class="tab-item" :class="{ active: currentTab === tab.name }" @click="currentTab = tab.name" > {{ tab.label }} </div> </div> <!-- 动态组件内容区(带 KeepAlive 缓存) --> <div class="tab-content"> <KeepAlive> <component :is="currentComponent" :user="currentUser" @update="handleUpdate" /> </KeepAlive> </div> <!-- 显示当前激活的 Tab 名称(调试用) --> <p style="margin-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-model="inputValue" placeholder="输入一些内容..." /> <p>输入内容:{{ inputValue }}</p> </div> `, setup() { const inputValue = ref('') return { inputValue } } } const TabList = { name: 'TabList', template: ` <div> <h3>📋 列表</h3> <ul> <li v-for="item in items" :key="item.id">{{ item.name }}</li> </ul> <button @click="addItem">添加项</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> <label><input type="checkbox" v-model="darkMode" /> 启用暗黑模式</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; } </style>

3. 关键点解析
核心概念代码实现说明
动态组件<component :is="currentComponent" />currentComponent是一个组件对象或注册名,Vue 会根据它的变化动态渲染不同组件。
Tab 切换点击.tab-item更新currentTab,再通过computed计算currentComponent使用v-for遍历tabs数组,维护currentTab响应式状态。
组件状态保持使用<KeepAlive>包裹<component>不加<KeepAlive>时,每次切换都会销毁旧组件并创建新组件,内部状态(如输入框内容)会丢失。加上后,组件实例被缓存,状态得以保留。
Props 传递:user="currentUser"绑定到动态组件。只要currentComponent对应的组件声明了props,就会正常接收。
自定义事件@update="handleUpdate"子组件可通过emit('update', data)向父组件通信,适用于任何动态组件。
内联组件定义使用defineComponent(或直接对象)在父文件中定义。实际项目推荐将 Tab 组件抽离为独立.vue文件,便于维护。

4. 运行效果说明
  • 点击首页→ 显示输入框,输入内容后切换到其他 Tab,再切回首页,输入内容依然存在(KeepAlive生效)。
  • 点击列表→ 显示列表和“添加项”按钮,点击添加新项,切换后列表状态保留。
  • 点击设置→ 显示当前用户(从父组件传递)和暗黑模式开关,状态独立。

5. 与路由的区别
  • 动态组件:适合同一页面内的局部切换(如设置面板、仪表盘)。
  • Vue Router:适合不同页面的切换,且拥有独立的 URL 和生命周期钩子。

7. 注意事项
  • 如果 Tab 组件之间需要独立的缓存策略,可以给<KeepAlive>添加include/exclude属性。
  • 动态组件的:is可以传组件对象(如TabHome)或组件名(字符串),但在<script setup>中,使用对象更直接。
  • currentComponentnull时,<component>不渲染任何内容,可用于占位或错误处理。
http://www.jsqmd.com/news/1079790/

相关文章:

  • WISV:无线感知语义验证如何加速边缘LLM分布式推理
  • C#:回车换行
  • 云原生 AI 平台:从模型仓库到弹性推理服务的全链路搭建
  • 一文读懂CUTTag:表观遗传研究的“精准定位神器”
  • 从Goncharov猜想到Bloch-Kriz构造:混合Tate动机与余李代数
  • 用 “WeChat AI Skill Builder“快速开发微信小程序「AI 能力」功能
  • 安居客App逆向分析:从抓包到参数签名算法还原实战
  • Codex 提示词工程——写出让 Codex 一次理解对的高效 Prompt
  • JiYuTrainer深度解析:破解极域电子教室控制的技术艺术
  • 草本外用养护货源怎么选?名氏草本舒缓贴全维度解析
  • 信号拟合框架sigfit:从数据到模型的工程实践指南
  • 【课程设计/毕业设计】基于 SpringBoot + 小程序的美妆电商综合管理平台 数字化美妆门店线上服务小程序 美妆商品智能推荐与购物交易系统设计与实现【附源码、数据库、万字文档】
  • 企业数据安全警报:为什么70%的组织都在担心数据泄露?
  • 自动驾驶仿真专用自动曝光白平衡ISP仿真Shader
  • 港口监控每天产生10万小时视频,90%都在“白看”?国标GB28181视频平台EasyGBS这套AI方案让安全隐患无处遁形
  • 创客匠人:私域直播如何搭建知识 IP 可持续变现体系
  • 使用 Docker Compose 部署 Dify
  • JS、浏览器——栈和队列(事件循环相关)
  • 移动端开发工具按键精灵手机版安卓/IOS开发必备键盘按键键码值(keyCode)对照表
  • 最值得大学生考的十大证书:2026年高含金量考证通关指南
  • 大模型训练全流程实战指南工具篇——大模型训练参数调优实战!
  • 【课程设计/毕业设计】基于小程序的校园社团资讯发布与交互系统设计与实现 高校学生社团组织管理信息化小程序设计与实现【附源码、数据库、万字文档】
  • 真实复盘:舵机软件研发的日常,没有捷径,只有深耕
  • Element UI el-upload 多文件上传踩坑与解决方案
  • 第三卷:《组合逻辑:没有记忆的“直肠子”侠客》
  • PCF80可以做共定位分析吗?从细胞邻近关系看懂真实肿瘤微环境
  • 智能旅游中的路线规划与体验提升
  • 人工排班不均引发员工投诉,智能排班平衡班次分配降低离职风险
  • 不止是补能设备!三款家用充电桩深度体验,解锁多元用车新方式
  • 工业级SRAM芯片高速低功耗存储方案