Vue开发实例(十)Tabs标签页打开、关闭与路由之间的关系

创建标签页

  • 一、创建标签页
  • 二、点击菜单展示新标签页
    • 1、将标签数据作为全局使用
    • 2、菜单点击增加标签页
    • 3、处理重复标签
    • 4、关闭标签页
  • 三、点击标签页操作
    • 问题1:点击标签页选中菜单进行高亮展示
    • 问题2:点击标签页路由也要跳转
  • 四、解决bug


先展示最终效果
在这里插入图片描述

一、创建标签页

  1. 创建一个Tabs/index.vue页面
<template><div><el-tabs v-model="editableTabsValue" type="card" closable><el-tab-pane:key="item.name"v-for="item in editableTabs":label="item.title":name="item.name"></el-tab-pane></el-tabs></div>
</template><script>
export default {name: "Tabss",data() {return {editableTabsValue: "1",editableTabs: [{title: "首页",name: "1",content: "首页",},{title: "Tab 1",name: "2",content: "Tab 1 content",},{title: "Tab 2",name: "3",content: "Tab 2 content",},],tabIndex: 1,};},
};
</script><style scoped>
div{height: auto;
}
</style>
  1. 修改Index.vue页面,在页面的路由锚点 router-view上方引入此页面
    在这里插入图片描述
    页面效果
    在这里插入图片描述

二、点击菜单展示新标签页

1、将标签数据作为全局使用

(1)将数据放到store.js中,作为全局

import Vue from 'vue'
import Vuex from 'vuex'
import moduleA from './module/moduleA.js';
import moduleB from './module/moduleB.js';Vue.use(Vuex)const state = {username: '牛牛',userState: 0,menu_data: [],isLoadRoute: false,editableTabsValue: '1',editableTabs: [{title: '首页',name: '首页',content: '首页'},{title: 'Tab 1',name: '2',content: 'Tab 1 content'},{title: 'Tab 2',name: '3',content: 'Tab 2 content'}]
}
const mutations = {setLoadRoute(state, data) {state.isLoadRoute = data},setUser(state, name) {state.username = name},setUserState(state, data) {state.userState += data},setMenuData(state, data) {state.menu_data = data},}
const getters = {getUserState(state) {let data;if (state.userState == 0) {data = '无效'} else {data = state.userState + '级'}return data;}
}
const modules = {a: moduleA,b: moduleB
}export default new Vuex.Store({state,mutations,getters,modules
})

(2)Tabs/index.vue 中的这两个数据 editableTabsValueeditableTabs 就从store中获取

注意:

  • 如果你的在data中这样写,可能会无法正常显示,建议用computed 方式来写。
<template><div><el-tabs v-model="editableTabsValue" type="card" closable><el-tab-pane:key="item.name"v-for="item in editableTabs":label="item.title":name="item.name"></el-tab-pane></el-tabs></div>
</template><script>
export default {name: "Tabs",data() {return {};},computed: {editableTabsValue: {get() {return this.$store.state.editableTabsValue;},set(val) {this.$store.state.editableTabsValue = val;},},editableTabs: {get() {return this.$store.state.editableTabs;},set(val) {this.$store.state.editableTabs = val;},},},
};
</script><style scoped>
div {height: auto;
}
</style>

页面效果是一样的
在这里插入图片描述

2、菜单点击增加标签页

(1)在 store/index.js 中将写死的数据editableTabs 内容删除,只剩下首页的那条
(2)在mutations添加 editableTabs 数据变更的方法 addEditableTabs,因为我定义的菜单数据的时候,没有title属性,所以这里我都用title来代表

参考代码:

import Vue from 'vue'
import Vuex from 'vuex'
import moduleA from './module/moduleA.js';
import moduleB from './module/moduleB.js';Vue.use(Vuex)const state = {username: '牛牛',userState: 0,menu_data: [],isLoadRoute: false,editableTabsValue: '1',editableTabs: [{title: '首页',name: '首页',content: '首页'}]
}
const mutations = {setLoadRoute(state, data) {state.isLoadRoute = data},setUser(state, name) {state.username = name},setUserState(state, data) {state.userState += data},setMenuData(state, data) {state.menu_data = data},addEditableTabs(state, tab) {state.editableTabs.push({title: tab.name,name: tab.name})state.editableTabsValue = tab.name}
}
const getters = {getUserState(state) {let data;if (state.userState == 0) {data = '无效'} else {data = state.userState + '级'}return data;}
}
const modules = {a: moduleA,b: moduleB
}export default new Vuex.Store({state,mutations,getters,modules
})

(3)给Aside/index.vue菜单增加点事件,selectMenu方法

<template><div style="height: 100%"><el-menubackground-color="#545c64"text-color="#ffffff"active-text-color="#ffd04b"class="el-menu-vertical-demo"router><el-menu-item:index="item.path"v-for="item in menu_data":key="item.name"@click="selectMenu(item)"><i :class="item.icon"></i>{{ item.name }}</el-menu-item></el-menu></div>
</template><script>
export default {name: "Aside",data() {return {};},computed: {menu_data: {get() {return this.$store.state.menu_data;},},},methods: {selectMenu(item) {this.$store.commit("addEditableTabs", item);},},
};
</script><style scoped>
.el-icon-location,
.el-icon-document,
.el-icon-setting {display: inline-flex;align-items: center;justify-content: center;
}
</style>

页面效果
在这里插入图片描述
问题:出现重复菜单名称标签

3、处理重复标签

store/index.js文件中的addEditableTabs 中判断,如果数据中已经有了,则不重复添加,只需切换即可
在这里插入图片描述

页面效果
在这里插入图片描述
现在就只有两个标签了,目前展示正常,但是没法关闭

4、关闭标签页

标签页添加关闭事件

el-tabs标签中添加 @tab-remove="removeTab",在method添加对应的方法

<template><div><el-tabsv-model="editableTabsValue"type="card"closable@tab-remove="removeTab"><el-tab-pane:key="item.name"v-for="item in editableTabs":label="item.title":name="item.name"></el-tab-pane></el-tabs></div>
</template><script>
export default {name: "Tabs",data() {return {};},methods: {removeTab(targetName) {let tabs = this.editableTabs;let activeName = this.editableTabsValue;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.editableTabsValue = activeName;this.editableTabs = tabs.filter((tab) => tab.name !== targetName);},},computed: {editableTabsValue: {get() {return this.$store.state.editableTabsValue;},set(val) {this.$store.state.editableTabsValue = val;},},editableTabs: {get() {return this.$store.state.editableTabs;},set(val) {this.$store.state.editableTabs = val;},},},
};
</script><style scoped>
div {height: auto;
}
</style>

页面效果
在这里插入图片描述

问题:

  1. 选中菜单,侧边栏没有进行对应的高亮展示
  2. 关闭了“一级菜单2”,但是页面内容还停留在“一级菜单2”,其实就是路由没有变

三、点击标签页操作

问题1:点击标签页选中菜单进行高亮展示

  1. 在Aside/index.vue中给 el-menu 设置属性 default-active
:default-active="this.$store.state.editableTabsValue"
  1. 将原来代码el-menu-item的index设置为"item.name"
:index="item.name"
  1. 加入路由跳转代码

因原来菜单点击,会根据index属性来跳转,index原来是path(路由地址),现在index属性更改为name了,则跳转不会生效,修改原来的router.js的代码,动态创建路由加入name属性(name:item.name),方便跳转。

修改router/index.js 代码

let oRouters = router.options.routes;
const buildRouter = ()=>{let data = store.state.menu_data;data.forEach(item=>{let new_router = {path:item.path,name:item.name,component:() => import('./components/'+item.component+'.vue')}oRouters[0].children.push(new_router);})router.addRoutes(oRouters)
}

Aside/index.vue的 selectMenu方法中,加入路由跳转代码(根据name跳转),仅需一行代码即可。

selectMenu(item){//点击菜单跳转路由this.$router.push({name:item.name})this.$store.commit("addEditableTabs",item);
}

页面效果,可以实现点击标签页,菜单跟着高亮显示了
在这里插入图片描述
Aside/index.vue 页面代码

<template><div style="height: 100%"><el-menubackground-color="#545c64"text-color="#ffffff"active-text-color="#ffd04b"class="el-menu-vertical-demo"router:default-active="this.$store.state.editableTabsValue"><el-menu-item:index="item.name"v-for="item in menu_data":key="item.name"@click="selectMenu(item)"><i :class="item.icon"></i>{{ item.name }}</el-menu-item></el-menu></div>
</template><script>
export default {name: "Aside",data() {return {};},computed: {menu_data: {get() {return this.$store.state.menu_data;},},},methods: {selectMenu(item) {//点击菜单跳转路由this.$router.push({ name: item.name });this.$store.commit("addEditableTabs", item);},},
};
</script><style scoped>
.el-icon-location,
.el-icon-document,
.el-icon-setting {display: inline-flex;align-items: center;justify-content: center;
}
</style>

问题2:点击标签页路由也要跳转

上面遗留的问题2,点击标签页,标签页下方的页面没有跟着跳转,下面修改这个问题

  1. 在Tabs页面的 el-tabs 添加 tab-click 事件
  2. 添加方法,利用路由的name来跳转
<template><div><el-tabsv-model="editableTabsValue"type="card"closable@tab-remove="removeTab"@tab-click="clickTab"><el-tab-pane:key="item.name"v-for="item in editableTabs":label="item.title":name="item.name"></el-tab-pane></el-tabs></div>
</template><script>
export default {name: "Tabs",data() {return {};},methods: {removeTab(targetName) {let tabs = this.editableTabs;let activeName = this.editableTabsValue;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.editableTabsValue = activeName;this.editableTabs = tabs.filter((tab) => tab.name !== targetName);},clickTab(target) {this.$router.push({ name: target.name });},},computed: {editableTabsValue: {get() {return this.$store.state.editableTabsValue;},set(val) {this.$store.state.editableTabsValue = val;},},editableTabs: {get() {return this.$store.state.editableTabs;},set(val) {this.$store.state.editableTabs = val;},},},
};
</script><style scoped>
div {height: auto;
}
</style>

效果展示
在这里插入图片描述

四、解决bug

  1. 关闭菜单后,菜单对应的路由没有跟着跳转
    仅需在关闭标签的方法removeTab,最后加上以下代码
this.$router.push({name:activeName})
  1. 首页不允许关闭
    在关闭标签的方法removeTab ,执行关闭之前,加入以下代码
if(targetName=='首页'){return ;
}
  1. 完整removeTab 代码
removeTab(targetName) {let tabs = this.editableTabs;let activeName = this.editableTabsValue;if(targetName=='首页'){return ;}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.editableTabsValue = activeName;this.editableTabs = tabs.filter(tab => tab.name !== targetName);this.$router.push({name:activeName})
}
  1. 还有一个潜藏的bug就是打开、关闭的顺序问题,先关闭前面的菜单会报错,后面解决

在这里插入图片描述报错代码如下

Uncaught runtime errors:Avoided redundant navigation to current location: "/index/menu2".NavigationDuplicated: Avoided redundant navigation to current location: "/index/menu2".at createRouterError (webpack-internal:///./node_modules/vue-router/dist/vue-router.esm.js:1720:15)at createNavigationDuplicatedError (webpack-internal:///./node_modules/vue-router/dist/vue-router.esm.js:1708:15)at HTML5History.confirmTransition (webpack-internal:///./node_modules/vue-router/dist/vue-router.esm.js:1946:18)at HTML5History.transitionTo (webpack-internal:///./node_modules/vue-router/dist/vue-router.esm.js:1887:8)at HTML5History.push (webpack-internal:///./node_modules/vue-router/dist/vue-router.esm.js:2165:10)at eval (webpack-internal:///./node_modules/vue-router/dist/vue-router.esm.js:2510:22)at new Promise (<anonymous>)at VueRouter.push (webpack-internal:///./node_modules/vue-router/dist/vue-router.esm.js:2509:12)at VueComponent.removeTab (webpack-internal:///./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!./node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./src/components/Tabs/index.vue?vue&type=script&lang=js:29:20)at invokeWithErrorHandling (webpack-internal:///./node_modules/vue/dist/vue.runtime.esm.js:2903:26)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/717480.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Android 基础入门 基础简介

1. 观察App运行日志 2.Android 开发设计的编程语言 koltin Java c c 3.工程目录结构 4.Gradle 5.build.gradle 文件解析 plugins {id("com.android.application")//用了哪些插件 主配置文件版本控制 所以这里不用写版本 }android {namespace "com.tiger.myap…

基于springboot+vue的二手车交易系统

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、阿里云专家博主、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战&#xff0c;欢迎高校老师\讲师\同行交流合作 ​主要内容&#xff1a;毕业设计(Javaweb项目|小程序|Pyt…

C++进阶(二) 多态

一、多态的概念 多态的概念&#xff1a;通俗来说&#xff0c;就是多种形态&#xff0c; 具体点就是去完成某个行为&#xff0c;当不同的对象去完成时会 产生出不同的状态。举个栗子&#xff1a;比如买票这个行为&#xff0c;当普通人买票时&#xff0c;是全价买票&#xff1b;学…

Java中的List

List集合的特有方法 方法介绍 方法名描述void add(int index,E element)在此集合中的指定位置插入指定的元素E remove(int index)删除指定索引处的元素&#xff0c;返回被删除的元素E set(int index,E element)修改指定索引处的元素&#xff0c;返回被修改的元素E get(int inde…

动态规划5,粉刷房子,买卖股票的最佳时期

粉刷房子 思路&#xff1a; 1.经验题目要求 dp[i][0] 表示&#xff1a;粉刷到 i 位置的时候&#xff0c;最后一个位置粉刷上红色&#xff0c;此时的最小花费。 dp[i][1] 表示&#xff1a;粉刷到 i 位置的时候&#xff0c;最后一个位置粉刷上蓝色&#xff0c;此时的最小花费。…

mybatis开发一个分页插件、mybatis实现分页、mybatis拦截器

mybatis开发一个分页插件、mybatis实现分页、mybatis拦截器 通过官网的mybatis插件说明可知&#xff0c;我们可以通过拦截器进行开发一个插件。 例如这样的&#xff1a; UserMapper mapper sqlSession.getMapper(UserMapper.class);// 开始分页MagicPage.startPage(1, 3);//…

Linux:线程的概念

个人主页 &#xff1a; 个人主页 个人专栏 &#xff1a; 《数据结构》 《C语言》《C》《Linux》 文章目录 前言一、线程的概念线程代码的简单示例 总结 前言 本文是对于线程概念的知识总结 一、线程的概念 在课本上&#xff0c;线程是比进程更轻量级的一种指向流 或 线程是在…

VS Code 的粘性滚动预览 - 类似于 Excel 的冻结首行

VS Code 的粘性滚动预览 - 类似于 Excel 的冻结首行功能&#xff0c;即滚动 UI 显示当前源代码范围。便于在代码行数比较多的时候更好的知道自己所在的位置。粘性滚动UI 显示用户在滚动期间所处的范围&#xff0c;将显示编辑器顶部所在的类/接口/命名空间/函数/方法/构造函数&a…

理解这几个安全漏洞,你也能做安全测试

01 短信炸弹 1、漏洞描述 短信轰炸攻击是常见的一种攻击&#xff0c;攻击者通过网站页面中所提供的发送短信验证码的功能处&#xff0c;通过对其发送数据包的获取后&#xff0c;进行重放&#xff0c;如果服务器短信平台未做校验的情况时&#xff0c;系统会一直去发送短信&…

JVM内部世界(内存划分,类加载,垃圾回收)

&#x1f495;"Echo"&#x1f495; 作者&#xff1a;Mylvzi 文章主要内容&#xff1a;JVM内部世界(内存划分,类加载,垃圾回收) 关于JVM的学习主要掌握三方面: JVM内存区的划分类加载垃圾回收 一.JVM内存区的划分 当一个Java进程开始执行时,JVM会首先向操作系统申…

实例驱动计算机网络

文章目录 计算机网络的层次结构应用层DNSHTTP协议HTTP请求响应过程 运输层TCP协议TCP协议面向连接实现TCP的三次握手连接TCP的四次挥手断开连接 TCP协议可靠性实现TCP的流量控制TCP的拥塞控制TCP的重传机制 UDP协议 网际层IP协议&#xff08;主机与主机&#xff09;IP地址的分类…

【创作回顾】17个月峥嵘创作史

#里程碑专区#、#创作者纪念日# 还记得 2022 年 10 月 05 日&#xff0c;我在CSDN撰写了第 1 篇博客——《关于测试工程师瓶颈和突围的一个思考》&#xff0c;也是我在全网发布的第一篇技术文章。 回想当时&#xff0c;这一篇的诞生过程并不轻松&#xff0c;不像是一篇网络文章…

【计算机网络】深度学习HTTPS协议

&#x1f493; 博客主页&#xff1a;从零开始的-CodeNinja之路 ⏩ 收录文章&#xff1a;【计算机网络】深度学习HTTPS协议 &#x1f389;欢迎大家点赞&#x1f44d;评论&#x1f4dd;收藏⭐文章 目录 一:HTTPS是什么二:HTTPS的工作过程三:对称加密四:非对称加密五:中间人攻击1…

【web | CTF】BUUCTF [HCTF 2018]WarmUp

天命&#xff1a;这题本地php代码是无法复现的 首先打开网站&#xff0c;啥也没有&#xff0c;查看源码 发现文件&#xff0c;打开访问一下看看&#xff0c;发现是代码审计 <?phphighlight_file(__FILE__);class emmm{public static function checkFile(&$page){$whit…

【学习总结】什么是DoS和DDoS

[Q&A] 什么是DoS DoS 是 “Denial of Service”&#xff08;拒绝服务&#xff09;的缩写&#xff0c;它是一种网络攻击方式&#xff0c;其目的是使目标计算机或网络资源无法为合法用户提供正常的服务。通过向目标系统发送大量请求、消耗其带宽、处理器或内存等资源&#…

13 双口 RAM IP 核

双口 RAM IP 核简介 双口 RAM IP 核有两个端口&#xff0c;它又分为伪双端口 RAM 和真双端口 RAM&#xff0c;伪双端口 RAM 一个端口只能读&#xff0c;另一个端口只能 写&#xff0c;真双端口 RAM 两个端口都可以进行读写操作。同时对存储器进行读写操作时就会用到双端口 RAM…

unity-1

创建游戏对象&#xff08;游戏物体&#xff09; 可通过unity中的菜单栏中的Gameobject创建&#xff1b;也可在Hierarchy&#xff08;层级&#xff09;中创建&#xff0c; 双击即可居中看到。 在Hierarchy空白处右键即可看到&#xff0c;能创建游戏对象。 在Scene框中&#x…

BioTech - ADMET的性质预测 概述

欢迎关注我的CSDN&#xff1a;https://spike.blog.csdn.net/ 本文地址&#xff1a;https://blog.csdn.net/caroline_wendy/article/details/136438192 ADMET&#xff0c;即 Absorption、Distribution、Metabolism、Excretion、Toxicity&#xff0c;吸收、分布、代谢、排泄、毒性…

Linux shell:补充命令的使用

目录 一.导读 二.正文 三.结语 一.导读 上一篇介绍了脚本的简单概念以及使用&#xff0c;现在补充一些命令。 二.正文 目前处于全局目录&#xff0c;通过mkdir创建名我为day01的文件。 通过cd命令day01 切换至day01文件当中。 使用vim文本编辑器文件名&#xff08;firstdir&…

【Python】进阶学习:pandas--query()用法详解

&#x1f4da;【Python】进阶学习&#xff1a;pandas–query()用法详解 &#x1f308; 个人主页&#xff1a;高斯小哥 &#x1f525; 高质量专栏&#xff1a;Matplotlib之旅&#xff1a;零基础精通数据可视化、Python基础【高质量合集】、PyTorch零基础入门教程&#x1f448; 希…