一、首先建一个vuex仓库,去存放路由和标签值
const tagsview = {
state: {
visitedviews: [
{
name: "welcome",
path: "/welcome",
title: "欢迎页"
}
], //存放所有浏览过的且不重复的路由数据
},
mutations: { //这
ADD_VISITED_VIEWS: (state, view) => { //打开新页签--添加路由数据的方法
if (state.visitedviews.some(v => v.path == view.path)) return;
state.visitedviews.push({
name: view.name,
path: view.path,
title: view.meta.name2 || 'no-title'
})
},
DEL_VISITED_VIEWS: (state, view) => { //关闭页签--删除路由数据的方法
for (let [i, v] of state.visitedviews.entries()) {
if (v.path == view.path) {
state.visitedviews.splice(i, 1)
break
}
}
},
DEL_ALL_VIEWS: (state) => {
state.visitedviews = []
}
},
actions: { //调用这里去触发mutations,如何调用?在组件内使用this.$store.dispatch('action中对应名字', 参数)
addVisitedViews({
commit
}, view) { //通过解构赋值得到commit方法
commit('ADD_VISITED_VIEWS', view) //去触发ADD_VISITED_VIEWS,并传入参数
},
delVisitedViews({
commit,
state
}, view) { //删除数组存放的路由之后,需要再去刷新路由,这是一个异步的过程,需要有回掉函数,所以使用并返回promise对象,也可以让组件在调用的时候接着使用.then的方法
//commit('DEL_VISITED_VIEWS',view)
return new Promise((resolve) => { //resolve方法:未来成功后回掉的方法
commit('DEL_VISITED_VIEWS', view);
resolve([...state.visitedviews]);
})
},
delAllViews({ commit, state }) {
return new Promise((resolve) => {
commit('DEL_ALL_VIEWS')
resolve([...state.visitedviews])
})
}
}
}
export default tagsview
二、搞一个组件,去放tab标签
<template id="">
<div class="tags-view-container" v-show='visitedViews.length>=0' style="overflow: hidden;">
<el-tabs class="tabViewClass" v-model="editableTabsValue" type="card" @tab-click="goRouterLink" @tab-remove="delSelectTag" :closable="closableB" style="width: 97%;
border-top: 1px solid #E4E7ED;float: left;">
<el-tab-pane
:key="tag.path"
v-for="tag in Array.from(visitedViews)"
:label="tag.title"
:name="tag.path"
>
</el-tab-pane>
</el-tabs>
<div style="width: 3%;height:40px;border-top: 1px solid #E4E7ED;border-bottom: 1px solid #E4E7ED;float: left;text-align: center;">
<i class="el-icon-delete" style="margin-top: 13px;" @click="closeAllTags"></i>
</div>
</div>
</template>
<script>
export default {
data() {
return {
editableTabsValue: '/',
closableB: false
}
},
computed: {
visitedViews() {
//store中取值
console.log(this.$store.state.tagsview.visitedviews)
return this.$store.state.tagsview.visitedviews;
}
},
methods: {
goRouterLink(tab, event) {
console.log(tab)
console.log(event)
this.$router.push({ path: tab.name })
},
handleTabsEdit(targetName, action) {
console.log(targetName)
console.log(action)
},
closeAllTags() {
let This = this
console.log('关闭所有路由')
this.$store.dispatch('delAllViews')
this.$router.push('/welcome')
let obj = {
name: "welcome",
path: "/welcome",
title: "欢迎页"
}
This.$store.state.tagsview.visitedviews.push(obj)
},
isActive(route) {
return route.path == this.$route.path;
},
addViewTags() {
let This = this
//路由改变时执行的方法
if (this.$route.name) {
const route = this.$route;
console.log(route,'看路由')
this.$store.dispatch("addVisitedViews", route);
this.editableTabsValue = this.$route.path
if(This.$store.state.tagsview.visitedviews.length == 1 && This.$store.state.tagsview.visitedviews[0].path == '/welcome'){
This.closableB = false
}else{
This.closableB = true
}
}
},
delSelectTag(routePath) {
let This = this
let route = this.$store.state.tagsview.visitedviews.filter(item => item.path == routePath)[0]
//先提交删除数据的方法,数组删除出掉数据后,如果关闭的是当前打开的路由需要将路由改为数组最后一次push进去的路由
this.$store.dispatch("delVisitedViews", route).then(views => {
if (this.isActive(route)) {
//只有在关闭当前打开的标签页才会有影响
let lastView = views.slice(-1)[0]; //选取路由数组中的最后一位
if (lastView) {
this.$router.push(lastView);
if(This.$store.state.tagsview.visitedviews.length == 1 && This.$store.state.tagsview.visitedviews[0].path == '/welcome'){
This.closableB = false
}else{
This.closableB = true
}
} else {
this.$router.push("/");
This.closableB = false
}
This.editableTabsValue = route.path
console.log(This.closableB)
}else{
console.log(This.$store.state.tagsview.visitedviews)
if(This.$store.state.tagsview.visitedviews.length == 1 && This.$store.state.tagsview.visitedviews[0].path == '/welcome'){
This.closableB = false
}else{
This.closableB = true
}
}
});
}
},
watch: {
$route() {
this.addViewTags();
}
}
};
</script>
<style scoped>
.tags-view-wrap {
/*background: #efeef0;*/
position: absolute;
top: 8px;
left: 0px;
width: 100%;
height: 32px;
overflow: hidden;
}
.tags-view-wrap .tags-view-item {
height: 30px;
line-height: 30px;
display: inline-block;
/*color: #fff;*/
/*background-color: #409EFF;*/
background-color: #dcdfe6;
color: #606266;
border: 1px solid #dcdfe6;
padding: 0 8px;
border-radius: 5px;
margin: 0 3px;
/*position: relative;*/
}
.tags-view-wrap .tags-view-item:hover {
/*color: rgb(221, 247, 5);*/
}
.tags-view-wrap .active {
/*color: rgb(221, 247, 5);*/
/* background: #409EFF; */
background: red;
color: #fff;
}
.tags-view-wrap .circleClose{
color: #606266;
cursor: pointer;
}
.tags-view-wrap .circleClose:hover{
color: #ccc;
}
</style>
三、将封装好的标签放到页面相应的位置上
四、大致效果