参考:https://blog.csdn.net/hjx154954264/article/details/104799141/
一、前期准备工作
1.在index.js里正常导入路由
//这里的Meta的comp设置,加上单引号为字符串,如果设置为路由,后续会把路由缓存进sessionStorage,缓存里面的数据是json格式, component 是一个vue文件,所以没办法解析,会报错
2.写导航菜单navmenu(开启路由模式)
3.写tab标签页
tabs的content用组件展示
(1)导入组件
(2)
二、动态添加tabs
1 watch: { 2 $route: function (to) { 3 //监听路由的变化,动态生成tabs 4 console.log(to); 5 let flag = true; //判断是否需要新增页面 6 const path = to.path; 7 console.log(Object.keys(to.Meta).length) 8 if (Object.keys(to.Meta).length != 0) { 9 for (let i = 0; i < this.$refs.tabs.length; i++) { 10 if (i != 0) { 11 //首页不判断 如果页面已存在,则直接定位当页面,否则新增tab页面 12 if (this.$refs.tabs[i].label == to.Meta.name) { 13 this.activeTab = this.$refs.tabs[i].name; //定位到已打开页面 14 flag = false; 15 break; 16 } 17 } 18 } 19 //新增页面 20 if (flag) { 21 //获得路由元数据的name和组件名 22 const thisName = to.Meta.name; //在index.js中定义的Meta 23 const thisComp = to.Meta.comp; 24 //对tabs的当前激活下标和tabs数量进行自加 25 let newActiveIndex = ++this.tabIndex + ""; 26 //动态双向追加tabs 27 this.tabsItem.push({ 28 title: thisName, 29 name: String(newActiveIndex), 30 closable: true, 31 ref: "tabs", 32 content: thisComp, 33 }); 34 this.activeTab = newActiveIndex; 35 /* 36 * 当添加tabs的时候,把当前tabs的name作为key,path作为value存入tabsPath数组中 37 * ///后面需要得到当前tabs的时候可以通过当前tabs的name获得path 38 * */ 39 if (this.tabsPath.indexOf(path) == -1) { 40 this.tabsPath.push({ 41 name: newActiveIndex, 42 path: path, 43 }); 44 } 45 } 46 } 47 }, 48 },
三、用sessionstorage保存tabs(否则一刷新标签页就恢复原样,只有首页)
mounted() { /* * 监听页面刷新事件 * 页面刷新前 需要保存当前打开的tabs的位置,刷新后按刷新前的顺序展示 * 使用js的sessionStorage保存刷新页面前的数据 * */ window.addEventListener("beforeunload", (e) => { sessionStorage.setItem( "tabsItem", JSON.stringify({ currTabsItem: this.tabsItem.filter((item) => item.name !== "1"), currTabsPath: this.tabsPath.filter((item) => item.name !== "1"), currActiveTabs: this.activeTab, currIndex: this.tabIndex, }) ); }); }, created() { /* * 使用js的sessionStorage读取刷新前的数据,并按刷新前的tabs顺序重新生成tabs * */ const sessionTabs = JSON.parse(sessionStorage.getItem("tabsItem")); if ( sessionTabs.currTabsItem.length != 0 && sessionTabs.currTabsPath.length != 0 ) { for (let i = 0; i < sessionTabs.currTabsItem.length; i++) { this.tabsItem.push({ title: sessionTabs.currTabsItem[i].title, name: sessionTabs.currTabsItem[i].name, closable: true, ref: sessionTabs.currTabsItem[i].ref, content: sessionTabs.currTabsItem[i].content, //这里不要把路由缓存进sessionStorage,因为缓存里面的数据是json格式, component 是一个vue文件,所以没办法解析,会报错(此处我的content已经改成了字符串了) }); } for (let j = 0; j < sessionTabs.currTabsPath.length; j++) { this.tabsPath.push({ name: sessionTabs.currTabsPath[j].name, path: sessionTabs.currTabsPath[j].path, }); } this.activeTab = sessionTabs.currActiveTabs; this.tabIndex = sessionTabs.currIndex; //避免强制修改url 出现浏览器的url输入框的路径和当前tabs选中的路由路径不匹配 const activePath = this.tabsPath.filter( (item) => item.name == this.activeTab ); this.$router.push({ path: activePath[0].path, }); } },
removeTab(targetName) { //删除Tab let tabs = this.tabsItem; //当前显示的tab数组 let activeName = this.activeTab; //点前活跃的tab //如果当前tab正活跃 被删除时执行 if (activeName === targetName) { tabs.forEach((tab, index) => { if (tab.name === targetName) { let nextTab = tabs[index + 1] || tabs[index - 1]; if (nextTab) { activeName = nextTab.name; this.tabClick(nextTab); } } }); } this.activeTab = activeName; this.tabsItem = tabs.filter((tab) => tab.name !== targetName); //在tabsPath中删除当前被删除tab的path this.tabsPath = this.tabsPath.filter((item) => item.name !== targetName); },
tabClick(thisTab) { /* * thisTab:当前选中的tabs的实例 * 通过当前选中tabs的实例获得当前实例的path 重新定位路由 * */ let val = this.tabsPath.filter((item) => thisTab.name == item.name); this.$router.push({ path: val[0].path, }); },
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。