🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
[TOC] ## tabs组件 在`src/layouts/TabsView.vue`新建多页签组件,找到官网`tabs`组件 ``` <template> <div> <div :style="{ marginBottom: '16px' }"> <a-button @click="add"> ADD </a-button> </div> <a-tabs v-model="activeKey" hide-add type="editable-card" @edit="onEdit"> <a-tab-pane v-for="pane in panes" :key="pane.key" :tab="pane.title" :closable="pane.closable"> {{ pane.content }} </a-tab-pane> </a-tabs> </div> </template> <script> export default { data() { const panes = [ { title: 'Tab 1', content: 'Content of Tab 1', key: '1' }, { title: 'Tab 2', content: 'Content of Tab 2', key: '2' }, ]; return { activeKey: panes[0].key, panes, newTabIndex: 0, }; }, methods: { callback(key) { console.log(key); }, onEdit(targetKey, action) { this[action](targetKey); }, add() { const panes = this.panes; const activeKey = `newTab${this.newTabIndex++}`; panes.push({ title: `New Tab ${activeKey}`, content: `Content of new Tab ${activeKey}`, key: activeKey, }); this.panes = panes; this.activeKey = activeKey; }, remove(targetKey) { let activeKey = this.activeKey; let lastIndex; this.panes.forEach((pane, i) => { if (pane.key === targetKey) { lastIndex = i - 1; } }); const panes = this.panes.filter(pane => pane.key !== targetKey); if (panes.length && activeKey === targetKey) { if (lastIndex >= 0) { activeKey = panes[lastIndex].key; } else { activeKey = panes[0].key; } } this.panes = panes; this.activeKey = activeKey; }, }, }; </script> ``` 去掉add功能,修改代码 ``` <template> <a-tabs v-model="activePage" type="editable-card" :hide-add="true" @edit="editPage"> <!-- edit 新增和删除页签的回调,在 type="editable-card" 时有效 --> <a-tab-pane v-for="page in pageList" :key="page.fullPath"> <span slot="tab" :pagekey="page.fullPath">{{ page.meta.title }}</span> </a-tab-pane> </a-tabs> </template> <script> export default { data() { return { activePage: "", pageList: [], // 页签的路由数组 }; }, created() { const route = this.$route; this.pageList.push(route); this.activePage = route.fullPath; }, watch: { $route: function (newRoute) { // 当前路由高亮 this.activePage = newRoute.fullPath; // 当前路由在页签中不存在时添加新页签 if (this.pageList.findIndex(item => item.fullPath == newRoute.fullPath) == -1) { this.pageList.push(newRoute); } } }, methods: { callback(key) { console.log(key); }, editPage(key, action) { this[action](key); // remove }, remove(key, next) { // 页签只有一个时 不能关闭 if (this.pageList.length === 1) { return this.$message.warning("这是最后一页,不能再关闭了"); } // 当前页签的索引 let index = this.pageList.findIndex(item => item.fullPath === key); // 删除当前页签 this.pageList.splice(index, 1); if (next) { this.$router.push(next); } else if (key === this.activePage) { index = index >= this.pageList.length ? this.pageList.length - 1 : index; this.activePage = this.pageList[index].fullPath; this.$router.push(this.activePage); } }, } }; </script> ``` 在BasicLayout.vue中引入 ``` <a-layout-content style="margin: 0 16px"> <!-- <router-view></router-view> --> <tabs-view></tabs-view> </a-layout-content> ``` ## CustomEvent自定义页签关闭事件 用法 ``` // 添加一个适当的事件监听器 obj.addEventListener("cat", function(e) { process(e.detail) }) // 创建并分发事件 var event = new CustomEvent("cat", {"detail":{"hazcheeseburger":true}}) obj.dispatchEvent(event) ``` 新建`src/plugins/tabs-page-plugin.js` ``` const TabsPagePlugin = { install(Vue) { Vue.mixin({ methods: { $closePage(closeRoute, nextRoute) { // CustomEvent() 创建一个自定义事件 // CustomEvent.detail 只读 任何时间初始化时传入的数据 const event = new CustomEvent("page:close", { detail: { closeRoute, nextRoute } }); window.dispatchEvent(event); } } }); } }; export default TabsPagePlugin; ``` 新建`src/plugins/index.js`,引入`TabsPagePlugin` ``` import TabsPagePlugin from "./tabs-page-plugin"; const Plugins = { install: function (Vue) { Vue.use(TabsPagePlugin); } }; export default Plugins; ``` `main.js`引入 ``` import Plugins from "@/plugins"; Vue.use(Plugins); ``` 修改`src/layouts/TabsView.vue` ``` <template> <a-tabs v-model="activePage" type="editable-card" :hide-add="true" @edit="editPage"> <!-- edit 新增和删除页签的回调,在 type="editable-card" 时有效 --> <a-tab-pane v-for="page in pageList" :key="page.fullPath"> <span slot="tab" :pagekey="page.fullPath">{{ page.meta.title }}</span> </a-tab-pane> </a-tabs> <div class="tabs-view-content"> <keep-alive> <router-view :key="$route.fullPath" ref="tabContent"/> </keep-alive> </div> </template> <script> export default { data() { return { activePage: "", pageList: [], // 页签的路由数组 }; }, created() { const route = this.$route; this.pageList.push(route); this.activePage = route.fullPath; // 自定义监听关闭事件 window.addEventListener("page:close", this.closePageListener); }, beforeDestroy() { window.removeEventListener("page:close", this.closePageListener); }, watch: { $route: function (newRoute) { // 当前路由高亮 this.activePage = newRoute.fullPath; // 当前路由在页签中不存在时添加新页签 if (this.pageList.findIndex(item => item.fullPath == newRoute.fullPath) == -1) { this.pageList.push(newRoute); } } }, methods: { callback(key) { console.log(key); }, editPage(key, action) { this[action](key); // remove }, remove(key, next) { // 页签只有一个时 不能关闭 if (this.pageList.length === 1) { return this.$message.warning("这是最后一页,不能再关闭了"); } // 当前页签的索引 let index = this.pageList.findIndex(item => item.fullPath === key); // 删除当前页签 this.pageList.splice(index, 1); if (next) { this.$router.push(next); } else if (key === this.activePage) { index = index >= this.pageList.length ? this.pageList.length - 1 : index; this.activePage = this.pageList[index].fullPath; this.$router.push(this.activePage); } }, closePageListener(event) { const { closeRoute, nextRoute } = event.detail; const closePath = typeof closeRoute === "string" ? closeRoute : closeRoute.path; this.remove(closePath, nextRoute); } } }; </script> ``` ## 使用 关闭当前页面:`this.$closePage(this.$route.fullPath);`