1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > 【通俗易懂】vue实现tagsview标签导航栏切换菜单功能【详细注释 都能看的懂】

【通俗易懂】vue实现tagsview标签导航栏切换菜单功能【详细注释 都能看的懂】

时间:2021-03-10 16:56:45

相关推荐

【通俗易懂】vue实现tagsview标签导航栏切换菜单功能【详细注释 都能看的懂】

前言:

后台系统现在基本都要有tagsview标签这个功能了,很多人是看网上的模板vue-element-admin内的tagsview。我也看了网上的很多资料和这个模板,但是很可惜,我是个小白,看了半天没看懂,也不知道如何复制,如何修改。所以我只能自己慢慢写一个这个功能,通过两天时间不断试错尝试,总算是写出来了功能。我相信不只有我一个人看不懂,那我就写个详细的攻略给你们看看吧,希望帮助更多的小白少掉点头发。如果看完还是不懂的可以评论问我。

效果图

基于

实现基于:vue element-ul vuex 右键菜单插件

思路:

利用vuex来实现动态响应

1,点击菜单获取菜单的名字用commit传给vuex内保存

2,tagsview组件拿到名字渲染出来。

3,添加点击事件,点击标签跳转对应路由。

4,通过动态class来设置高亮效果

5,右键菜单通过插件来实现

6,给叉号加点击事件,点击后关闭当前标签。通过传参拿到当前项和index来实现

功能:目前是主要的功能,更多细节功能可以扩展

1,点击菜单增加一个对应名字的tagsview标签

2,点击tagsview标签可以跳转对应的菜单路由

3,tagsview标签会根据跳转的页面不同高亮显示

4,点击关闭按钮可以关闭tagsview标签

5,点击tagsview标签会对应展开菜单,并选中对应菜单

6,右键tagsview标签可以出现菜单,里面有关闭和关闭全部选项

7,点击右键菜单内关闭会关闭一个,点击关闭全部会把所有tagsview标签栏清空

8,关闭时,如果关闭的是最右边的则向左边tagsview标签跳转路由,如果不是则向右跳转。如果删除后没有tagsview标签了,那么自动跳转首页

9,所有tagsview标签关闭后,标签导航栏隐藏不显示。有tagsview标签时显示。

上代码:

创建一个tagsview.vue组件:把这个代码复制进去。

<template><!-- calss添加了一个样式 --><div class="tagsbox"><div@contextmenu.prevent="openMenu(item,$event)":class="isActive(item.url)?'active':''"class="tagsview"v-for="(item, index) in tags":key="index"@click="tagsmenu(item)">{{item.name }}<!-- 这个地方一定要click加个stop阻止,不然会因为事件冒泡一直触发父元素的点击事件,无法跳转另一个路由 --><span class="el-icon-close tagsicon" @click.stop="handleClose(item,index)"></span><ul v-show="visible" class="contextmenu" :style="{left:left+'px',top:top+'px'}"><li @click.stop="handleClose(item,index)">关闭</li><li @click.stop="cleartags($route.path)">关闭所有</li></ul></div></div></template><script>//这个就是导入vuex的数据,配合下面...map用import {mapState, mapMutations } from "vuex";export default {data() {return {//右键菜单隐藏对应布尔值visible: false,//右键菜单对应位置top: 0,left: 0}},computed: {//引入vuex中state中的tags数据,一样this调用就行...mapState(["tags"]),},watch:{//监听右键菜单的值是否为true,如果是就创建全局监听点击事件,触发closeMenu事件隐藏菜单,如果是false就删除监听visible(value) {if (value) {document.body.addEventListener('click', this.closeMenu)} else {document.body.removeEventListener('click', this.closeMenu)}}},methods: {//引入vuex中mutation方法,可以直接this.xxx调用他...mapMutations(["closeTab", "cleartagsview"]),//点击叉叉删除的事件handleClose(item, index) {//先把长度保存下来后面用来比较做判断条件let length = this.tags.length - 1;//vuex调方法,上面...map引入的vuex方法,不会这种方法的看vue官网文档this.closeTab(item);// 如果关闭的标签不是当前路由的话,就不跳转if (item.url !== this.$route.path) {return;}// 判断:如果index和length是一样的,那就代表都是一样的长度,就是最后一位,那就往左跳转一个if (index === length) {//再判断:如果length=0,也就是说你删完了所有标签if (length === 0) {//那么再判断:如果当前路由不等于index,也就是我首页的路由if (this.$route.path !== "/index") {//那么就跳转首页。这一步的意思是:如果删除的最后一个标签不是首页就统一跳转首页,如果你删除的最后一个标签是首页标签,已经在这个首页路由上了,你还跳个什么呢。这不重复操作了吗。this.$router.push({path: "/index" });}} else {//那么,如果上面的条件都不成立,没有length=0.也就是说你还有好几个标签,并且你删除的是最后一位标签,那么就往左边挪一位跳转路由this.$router.push({path: this.tags[index - 1].url });}} else {// 如果你点击不是最后一位标签,点的前面的,那就往右边跳转this.$router.push({path: this.tags[index].url });}},//点击跳转路由tagsmenu(item) {//判断:当前路由不等于当前选中项的url,也就代表你点击的不是现在选中的标签,是另一个标签就跳转过去,如果你点击的是现在已经选中的标签就不用跳转了,因为你已经在这个路由了还跳什么呢。if (this.$route.path !== item.url) {//用path的跳转方法把当前项的url当作地址跳转。this.$router.push({path: item.url });}},//通过判断路由一致返回布尔值添加class,添加高亮效果isActive(route) {return route === this.$route.path},//右键事件,显示右键菜单,并固定好位置。openMenu(tag, e) {this.visible = truethis.selectedTag = tagconst offsetLeft = this.$el.getBoundingClientRect().left this.left = e.clientX - offsetLeft + 210 //右键菜单距离左边的距离this.top = e.clientY +10 //右键菜单距离上面的距离 这两个可以更改,看看自己的右键菜单在什么位置,自己调},//隐藏右键菜单closeMenu() {this.visible = false},//右键菜单关闭所有选项,触发vuex中的方法,把当前路由当参数传过去用于判断cleartags(val){this.cleartagsview(val)}},};</script><style lang="scss" scoped>//标签导航样式.tagsview {cursor: pointer;margin-left: 4px;height: 26px;line-height: 26px;padding: 0 8px;border: 1px solid #d8dce5;border-radius: 5px;color: #000;font-size: 12px;display: inline-block;}//叉号鼠标经过样式.tagsicon:hover{color: #f56c6c;}//标签高亮.active{background-color: #40ba84;color: #fff;}//右键菜单样式.contextmenu {margin: 0;background: #fff;z-index: 100;position: absolute;list-style-type: none;padding: 5px 0;border-radius: 4px;font-size: 12px;font-weight: 400;color: #333;box-shadow: 2px 2px 3px 0 rgba(0, 0, 0, .3);li {margin: 0;padding: 7px 16px;cursor: pointer;&:hover {background: #eee;}}}</style>

菜单栏部分

给个点击事件,把你们循环的菜单每一项拿出来传给vuex保存,用来后面渲染标签

通过commit把每一项菜单的数据传给vuex,这个地方也可以用console.log看一下你的每一项内path和name之类的是什么,找一个跟你路由中一致的用于后续判断依据。这个每一项就是传进来的val,写法就是val.path这样,查看点击后他会返回什么。看看跟你的当前跳转的路由path是否一样,如果是一样的就可以用path来做判断。如果是name一样就用name判断。

methods:{//点击把菜单的名字传出去clickMenu(val){this.$mit("pushtags",val)}}

主组件的部分:注意,这个不要直接复制了,你看下我tagsview组件放的位置就行了,可以自己调整位置

<template><div><!-- elementul中布局组件 --><el-container style="height: 100vh;"><!-- 左侧菜单部分 --><el-aside :width="subwidth"><!-- 菜单组件 --><nav-left></nav-left></el-aside><el-container><!-- 头部部分 --><el-header><!-- 头部组件 --><headers></headers></el-header><!-- 标签导航栏组件 --><tagsview></tagsview><!-- 内容部分 --><el-main><!-- 用if判断路由元信息内keepAlive是否为true如果是就缓存,如果缓存显示缓存的,如果不缓存就用不缓存的路由视图 --><keep-alive v-if="$route.meta.keepAlive"><router-view></router-view></keep-alive><router-view v-else></router-view></el-main></el-container></el-container></div></template><script>//引入vuex中的state,不了解的参考vuex文档import {mapState} from 'vuex'//菜单组件import navLeft from "@/components/navLeft"//头部组件import Headers from '../components/headers.vue';//引入tagsview组件import tagsview from "@/views/tagsview/tagsview.vue"export default {data(){return{//菜单的宽度,默认给个200subwidth:'200px'}},components:{//菜单navLeft,//头部Headers,//引入tagsview组件tagsview},computed:{//引入vuex中state的变量,可以直接this.xxx调用到...mapState(["isCollapse"]),},watch:{//监听vuex中的变量如果变动了就赋值,从而改变菜单栏缩小展开isCollapse(){if(this.isCollapse){this.subwidth='64px'}else{this.subwidth='200px'}}},};</script><style lang="scss" scoped>//这些是布局组件内自带的,去elementul复制然后改改.el-header, .el-footer {background-color: #fff;color: #333;line-height: 60px;box-shadow: 0 1px 4px rgba(0, 21, 41, 0.08);}//左侧菜单栏样式.el-aside {background-color: #001529;color: #333;text-align: left;line-height: 56px;//下面四个是菜单折叠动画效果transition: width 0.15s;-webkit-transition: width 0.15s;-moz-transition: width 0.15s;-webkit-transition: width 0.15s;-o-transition: width 0.15s;}//内容区域.el-main {background-color: #E9EEF3;color: #333;}body > .el-container {margin-bottom: 40px;}.el-container:nth-child(5) .el-aside,.el-container:nth-child(6) .el-aside {line-height: 260px;}.el-container:nth-child(7) .el-aside {line-height: 320px;}</style>

vuex部分:

import Vue from 'vue'import Vuex from 'vuex'import router from '../router/index.js'Vue.use(Vuex)export default new Vuex.Store({state: {//tags数组tags:[],//tagsview标签显示隐藏isCollapse:false},mutations: {pushtags(state,val){//如果等于-1说明tabs不存在那么插入,否则什么都不做//findindex找角标,循环判断一下,如果等于那么就代表有相同的,就不必添加,如果找不到那就是-1.就添加let result = state.tags.findIndex(item => item.name === val.name)result === -1 ? state.tags.push(val) : ''},//关闭标签closeTab(state, val) {//同上,找角标,然后用角标的位置对应删除一位。splice:这是数组的删除方法let result = state.tags.findIndex(item => item.name === val.name)state.tags.splice(result, 1)},//关闭所有tagsview标签cleartagsview(state,val){//清空数组state.tags=[]//跳转到首页,val接受传过来的当前路由if(val !== "/index"){router.push({path:"/index"})}},//改变tagsview显示隐藏changeisshow(state){state.isCollapse=!state.isCollapse}},actions: {},modules: {}})

右键菜单实现

第一步,安装组件

npm install vue-contextmenu --save

第二步:引入到main.js文件

import VueContextMenu from 'vue-contextmenu'Vue.use(VueContextMenu)

第三步:使用,放在你想要弹出的地方,具体位置看我代码,放在了div上

contextmenu:这是弹出组件

prevent:这是修饰符,意思是右键的时候不要弹出默认的菜单,默认的菜单就是你们平常在电脑桌面上右键刷新的那个右键菜单。让他别出来。

@contextmenu.prevent="openMenu(item,$event)"

点击标签左侧菜单也选中对应的菜单,子菜单自动展开选中功能

这个功能我当时乍一想也觉得有点复杂,后来发现elementul自带一个属性一句话解决

没错就这一句话,加在el-menu上,他就会根据当前路由自动激活对应菜单。注意是menu不是menu-item。最外层的容器

:default-active="$route.path"

标签切换时自动高亮

是这一句话的作用,其实就一个逻辑,根据当前路由判断一下是不是一样,如果是一样的路由,那就给他加个class。这个active我已经css写好样式了。添加就亮不添加就不亮

:class="isActive(item.url)?'active':''"

右键关闭所有

首先右键关闭我就直接再调用了一次叉号的方法完事。

这里要说的是关闭所有的小注意项:

关闭所有很明显很简单就是把数组清空,这里注意清空要用【】不能用 " ",如果用 " "表示清空就会报错。

像这样:

//关闭所有tagsview标签cleartagsview(state,val){//像这里一样后面加的是[]state.tags=[]//跳转到首页,val接受传过来的当前路由if(val !== "/index"){router.push({path:"/index"})}},

注意项:

1,样式可以改的,比如我用的div,你们可以用tag组件,或者tags组件或者自己写div,span之类的循环也行。这个自行更改

2,我是用的el-menu组件写的侧边栏菜单,所以我用它自带的属性开启路由模式了,所以url就是我的路由,我这个组件内有很多用path和url来对比判断的方法,因为我url和path是一致的,所以我可以这么用,你们用的时候一定要看下自己的路由信息哪个是一样的,有些人是name一样,那就换成name。这点很重要,不然不生效!!!

3,如果中途有问题,建议多用log看看,然后可以用alert弹框来测试一下是否执行某些地方。这样就很好更改了。

4,你的标签导航栏组件引入主组件结构内,放在全局,因为是所有页面都要用的,自己看看放什么位置好,自己选中,我是放在了页头的下面,有些人会放在内容部分的上面。随意

5,vuex使用会实时更新,但是刷新也会没有,如果你想要一直存在,就保存到本地去。

如果看了还是有不了解的可以评论提问

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。