自己封装的Tagsview
Tagsview组件,具体要根据项目需改的地方 组件内都有备注
<template>
<!-- calss添加了一个样式 -->
<div class="tagsbox">
<div
v-for="(item, index) in tags"
:key="index"
:class="isActive(item.path) ? 'active' : ''"
class="tagsview"
@contextmenu.prevent="openMenu(item, $event)"
@click="tagsmenu(item)"
>
{{ item.name }}
<!-- 这个地方一定要click加个stop阻止,不然会因为事件冒泡一直触发父元素的点击事件,无法跳转另一个路由 -->
<!-- 给首页去掉XX按钮 -->
<span
v-if="index != 0"
class="el-icon-close tagsicon"
@click.stop="handleClose(item, index)"
/>
<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
};
},
mounted() {
// console.log(this.tags, 'tags111111');
},
computed: {
// 引入vuex中state中的tags数据,一样this调用就行
...mapState('fhyctags', ['tags'])
// ...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('fhyctags', ['closeTab', 'cleartagsview']),
// 点击叉叉删除的事件
handleClose(item, index) {
// console.log(item, index, 'XXXX');
// 缓存状态传值
this.$store.commit('fhyctags/isTabviewFalse');
// 先把长度保存下来后面用来比较做判断条件
const length = this.tags.length - 1;
// vuex调方法,上面...map引入的vuex方法,不会这种方法的看vue官网文档
this.closeTab(item);
// console.log(item, 'itemitem');
// 如果关闭的标签不是当前路由的话,就不跳转
if (item.path !== this.$route.path) {
return;
}
// 判断:如果index和length是一样的,那就代表都是一样的长度,就是最后一位,那就往左跳转一个
if (index === length) {
// console.log(index, length, 'changdu');
// 再判断:如果length=0,也就是说你删完了所有标签
if (length === 0) {
// 那么再判断:如果当前路由不等于index,也就是我首页的路由
// if (this.$route.path !== '/index') {
if (this.$route.path !== '/loadForecasting/home/homeIndex') {
// 缓存状态传值
this.$store.commit('fhyctags/isTabviewFalse');
// 那么就跳转首页。这一步的意思是:如果删除的最后一个标签不是首页就统一跳转首页,如果你删除的最后一个标签是首页标签,已经在这个首页路由上了,你还跳个什么呢。这不重复操作了吗。
// this.$router.push({ path: '/index' })
this.$router.push({ path: '/loadForecasting/home/homeIndex' });
// this.reload();
}
} else {
// 缓存状态传值
this.$store.commit('fhyctags/isTabviewFalse');
// 那么,如果上面的条件都不成立,没有length=0.也就是说你还有好几个标签,并且你删除的是最后一位标签,那么就往左边挪一位跳转路由
this.$router.push({ path: this.tags[index - 1].path });
// this.$router.push({ path: this.tags[index - 1].url });
}
} else {
// 缓存状态传值
this.$store.commit('fhyctags/isTabviewFalse');
// 如果你点击不是最后一位标签,点的前面的,那就往右边跳转
this.$router.push({ path: this.tags[index].path });
// this.$router.push({ path: this.tags[index].url });
}
},
// 点击跳转路由
tagsmenu(item) {
// 缓存状态传值
this.$store.commit('fhyctags/isTabviewTrue');
console.log(item, 'tags对象');
// 判断:当前路由不等于当前选中项的url,也就代表你点击的不是现在选中的标签,是另一个标签就跳转过去,如果你点击的是现在已经选中的标签就不用跳转了,因为你已经在这个路由了还跳什么呢。
if (this.$route.path !== item.path) {
// 用path的跳转方法把当前项的url当作地址跳转。
this.$router.push({ path: item.path });
}
},
// 通过判断路由一致返回布尔值添加class,添加高亮效果
isActive(route) {
// console.log(route, '动态class');
return route === this.$route.path;
},
// 右键事件,显示右键菜单,并固定好位置。
openMenu(tag, e) {
console.log(this.this.$route, 'llllllll');
this.visible = true;
// if(this.this.$route.path)
this.selectedTag = tag;
const offsetLeft = this.$el.getBoundingClientRect().left;
this.left = e.clientX - offsetLeft + 10; // 右键菜单距离左边的距离
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: 30px;
line-height: 30px;
padding: 0 10px;
border: 1px solid #d8dce5;
border-radius: 5px;
color: #000;
font-size: 14px;
display: inline-block;
}
//叉号鼠标经过样式
.tagsicon:hover {
color: #f56c6c;
}
//标签高亮
.active {
background-color: #75b9e2;
// 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, 0.3);
li {
margin: 0;
padding: 7px 16px;
cursor: pointer;
&:hover {
background: #eee;
}
}
}
</style>
/store/modules内新建tagsView.js
const state = {
tags: [],
// tagsview标签显示隐藏
isCollapse: false,
// 判断缓存
isTabview: true
}
const mutations = {
// 更改缓存状态
isTabviewFalse(state) {
state.isTabview = false
},
// 更改缓存状态
isTabviewTrue(state) {
state.isTabview = true
},
// 全局方法
pushtags(state, val) {
// console.log(val)
// 如果等于-1说明tabs不存在那么插入,否则什么都不做
// findindex找角标,循环判断一下,如果等于那么就代表有相同的,就不必添加,如果找不到那就是-1.就添加
const result = state.tags.findIndex(item => item.name === val.name)
console.log(result, 1)
result === -1 ? state.tags.push(val) : ''
console.log(result, 2)
},
// 关闭标签
closeTab(state, val) {
// 同上,找角标,然后用角标的位置对应删除一位。splice:这是数组的删除方法
const result = state.tags.findIndex(item => item.name === val.name)
state.tags.splice(result, 1)
},
// 关闭所有tagsview标签
cleartagsview(state, val) {
// 清空数组 此处更改为项目内的首页路由保证清除全部时显示首页
// state.tags = []
state.tags = [{
name: '首页',
path: '/loadForecasting/home/homeIndex'
}]
// 跳转到首页,val接受传过来的当前路由 此处更改为项目内的首页路由
if (val !== '/loadForecasting/home/homeIndex') {
router.push({ path: '/loadForecasting/home/homeIndex' })
}
},
// 改变tagsview显示隐藏
changeisshow(state) {
state.isCollapse = !state.isCollapse
}
}
const actions = {
}
export default {
namespaced: true,
state,
mutations,
actions
}
最后在/store/index文件内引入
import Vue from 'vue'
import Vuex from 'vuex'
import app from './modules/app'
import user from './modules/user'
import tagsView from './modules/tagsView'
import permission from './modules/permission'
import settings from './modules/settings'
import getters from './getters'
Vue.use(Vuex)
const store = new Vuex.Store({
modules: {
app,
user,
tagsView,//组件
permission,
settings,
},
getters
})
export default store

浙公网安备 33010602011771号