实现同一个组件页面通过不同的tab标签页打开
Posted 千秋岁
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了实现同一个组件页面通过不同的tab标签页打开相关的知识,希望对你有一定的参考价值。
首先展示一下效果页面
将标签存放在Tags.vue,使用组件传值进行切换。增加keep-alive缓存机制
1、在home页面或主页面注册tabs组件
1 <el-main style="background-color:#eaedf1"> 2 <!-- 标签组件 --> 3 <tabs></tabs> 4 <router-view></router-view> 5 <!-- 增加keep-alive缓存机制 --> 6 <keep-alive :include="tagsList"> 7 <router-view></router-view> 8 </keep-alive> 9 </el-main> 10 11 在home页面或主页面注册tabs组件
2、在home页面或者主页面进行传值
1 <script> 2 import Tabs from \'@/components/common/Tags.vue\' // 引入Tags组件 3 import bus from \'@/components/common/bus.js\' // 组件传值使用的bus 4 export default { 5 created() { 6 // 用于keep-alive缓存,只有在标签页列表里的页面才使用keep-alive,即关闭标签之后就不保存到内存中了。 7 bus.$on(\'tags\', msg => { 8 let arr = [] 9 for (let i = 0, len = msg.length; i < len; i++) { 10 msg[i].name && arr.push(msg[i].name) 11 } 12 this.tagsList = arr 13 }) 14 }, 15 components: { 16 tabs: Tabs, // 注册tabs组件 17 bus, // 注册bus组件传值公共文件 18 }, 19 data() { 20 return { 21 tagsList: [], 22 } 23 }, 24 methods: {}, 25 } 26 </script>
3、新建一个bus.js文件,通用bus.js组件传值
1 import Vue from \'vue\'; 2 export default new Vue()
4、Tags.vue组件
1 <template> 2 <div class="tags" v-if="showTags"> 3 <!-- 标签列表 --> 4 <ul> 5 <li 6 class="tags-li" 7 v-for="(item,index) in tagsList" 8 :class="{\'active\': isActive(item.path)}" 9 :key="index" 10 > 11 <router-link :to="item.path" class="tags-li-title">{{item.title}}</router-link> 12 <span class="tags-li-icon" @click="closeTags(index)"> 13 <i class="el-icon-close"></i> 14 </span> 15 </li> 16 </ul> 17 <div class="tags-close-box"> 18 <!-- elementUi下拉菜单 --> 19 <el-dropdown @command="handleTags"> 20 <el-button size="mini" type="primary"> 21 标签选项 22 <i class="el-icon-arrow-down el-icon--right"></i> 23 </el-button> 24 <el-dropdown-menu size="small" slot="dropdown"> 25 <el-dropdown-item command="other">关闭其他</el-dropdown-item> 26 <el-dropdown-item command="all">关闭所有</el-dropdown-item> 27 </el-dropdown-menu> 28 </el-dropdown> 29 </div> 30 </div> 31 </template> 32 33 <script> 34 import bus from "./bus"; // 引入通用组件传值组件 35 export default { 36 data() { 37 return { 38 tagsList: [], // 存放所有标签 39 }; 40 }, 41 methods: { 42 // 当前选中标签 43 isActive(path) { 44 return path === this.$route.fullPath; 45 }, 46 // 关闭单个标签 47 closeTags(index) { 48 const delItem = this.tagsList.splice(index, 1)[0]; 49 const item = this.tagsList[index] 50 ? this.tagsList[index] 51 : this.tagsList[index - 1]; 52 if (item) { 53 delItem.path === this.$route.fullPath && this.$router.push(item.path); 54 } else { 55 this.$router.push("/"); 56 } 57 }, 58 // 关闭全部标签 59 closeAll() { 60 this.tagsList = []; 61 this.$router.push("/"); 62 }, 63 // 关闭其他标签 64 closeOther() { 65 const curItem = this.tagsList.filter(item => { 66 return item.path === this.$route.fullPath; 67 }); 68 this.tagsList = curItem; 69 }, 70 // 设置标签 71 setTags(route) { 72 const isExist = this.tagsList.some(item => { 73 return item.path === route.fullPath; 74 }); 75 if (!isExist) { 76 if (this.tagsList.length >= 8) { 77 this.tagsList.shift(); 78 } 79 this.tagsList.push({ 80 title: route.meta.title, 81 path: route.fullPath, 82 name: route.matched[1].components.default.name 83 }); 84 } 85 bus.$emit("tags", this.tagsList); // 组件传值 86 }, 87 // 点击标签下拉选项(关闭其他或者关闭所有) 88 handleTags(command) { 89 command === "other" ? this.closeOther() : this.closeAll(); 90 } 91 }, 92 computed: { 93 // 大于0则显示标签组件 94 showTags() { 95 return this.tagsList.length > 0; 96 } 97 }, 98 watch: { 99 // 当$route发生变化重新赋值 100 $route(newValue, oldValue) { 101 this.setTags(newValue); 102 } 103 }, 104 created() { 105 this.setTags(this.$route); 106 } 107 }; 108 </script> 109 110 111 <style> 112 .tags { 113 position: relative; 114 height: 30px; 115 overflow: hidden; 116 background: #fff; 117 padding-right: 120px; 118 box-shadow: 0 5px 10px #ddd; 119 } 120 121 .tags ul { 122 box-sizing: border-box; 123 width: 100%; 124 height: 100%; 125 } 126 127 .tags-li { 128 float: left; 129 margin: 3px 5px 2px 3px; 130 border-radius: 3px; 131 font-size: 12px; 132 overflow: hidden; 133 cursor: pointer; 134 height: 23px; 135 line-height: 23px; 136 border: 1px solid #e9eaec; 137 background: #fff; 138 padding: 0 5px 0 12px; 139 vertical-align: middle; 140 color: #666; 141 -webkit-transition: all 0.3s ease-in; 142 -moz-transition: all 0.3s ease-in; 143 transition: all 0.3s ease-in; 144 } 145 146 .tags-li:not(.active):hover { 147 background: #f8f8f8; 148 } 149 150 .tags-li.active { 151 color: #fff; 152 } 153 154 .tags-li-title { 155 float: left; 156 max-width: 80px; 157 overflow: hidden; 158 white-space: nowrap; 159 text-overflow: ellipsis; 160 margin-right: 5px; 161 color: #666; 162 } 163 164 .tags-li.active .tags-li-title { 165 color: #fff; 166 } 167 .tags-li.active { 168 border: 1px solid #409EFF; 169 background-color: #409EFF; 170 } 171 a { 172 text-decoration: none; 173 } 174 .tags-close-box { 175 position: absolute; 176 right: 0; 177 top: 0; 178 box-sizing: border-box; 179 padding-top: 1px; 180 text-align: center; 181 width: 110px; 182 height: 30px; 183 background: #fff; 184 box-shadow: -3px 0 15px 3px rgba(0, 0, 0, 0.1); 185 z-index: 10; 186 } 187 </style>
以上是关于实现同一个组件页面通过不同的tab标签页打开的主要内容,如果未能解决你的问题,请参考以下文章
antd源码分析之——标签页(tabs 2.Tabs关键组件功能实现)
vue中tab标签页keep-alive二级路由+删除指定缓存页面