前言
当页面路由变化时,然后生成一个tag标签,点击每个tag标签可以跳转到不同的页面
直接上代码
- tag标签组件
// tagView.vue
<template>
<div class="tagwrap">
<!--
1. 在router-link中,to已经绑定了点击跳转的事件,
2. 所以在router-link中绑定@click点击事件是没有作用的,
3. 可以在router-link标签里面去定义一个标签去绑定@click点击事件
4. 设置点击时的css样式绑定class,运用三目运算符
:class="isActive(route) ? active : ''"
-->
<router-link
:to="{ path: tagroute.path }"
class="routerlink"
v-for="tagroute in tagList"
:key="tagroute.path"
:class="isActive(tagroute) ? active : ''"
>
{{ tagroute.title }}
<!--
设置关闭字体图标,设置点击事件
设置点击事件的.prevent.stop修饰符,方式点击事件冒泡上去
-->
<span class="el-icon-close" @click.prevent.stop="delSelectTag(tagroute)"></span>
</router-link>
</div>
</template>
<script>
export default {
data: function() {
return {
active: "active",
tagViewBg: "tagViewBg"
};
},
methods: {
// 判断tag路由选中状态, route为当前点击的标签的路由
isActive: function(tagroute) {
/**
* 1. route.path 遍历tagList中的我的标签route的path
* 2. this.$route.path 点击当前路由对象的path
* 3. 判断是否一致,一致的话表示当前为选中状态
*/
return tagroute.path == this.$route.path;
},
delSelectTag: function(tagroute) {
/**
* 1. 调用vuex中删除标签的方法,将当前标签对象tagroute传进去,进行异步处理
* 2. data为promise异步操作处理成功后返回的的数据
*/
this.$store.dispatch("deleteTag", tagroute).then(data => {
// 判断当前删除的标签的选中状态,选中的话,就跳到最后一个,未选中的话则不需要跳转
if (this.isActive(tagroute)) {
// slice(-1)选中data数组中最后一个元素并返回放在一个数组中
const lastRoute = data.slice(-1)[0];
// 判断数组中最后一个标签是否还存在,不存在的话就跳到首页index
if (lastRoute) {
// 路由跳转到最后一路由
this.$router.push(lastRoute);
} else {
/**
* 当页面跳转到首页时,watch侦听器会侦听到路由的变化;
* 会再次执行储存路由状态到vuex中的操作,此时在首页会多出来一个标签;
* 此时需要在侦听器中进行判断,当变化的路由是 index 时,不进行储存操作
*/
this.$router.replace({ path: '/index' })
}
}
});
}
},
computed: {
tagList: function() {
let tagLists = this.$store.getters.tagList;
return tagLists;
}
},
watch: {
// 直接监听路由的变化,当路由变化时,将当前路由对象保存到vuex当中去
$route: function() {
console.log("this.$route>>>>>>>>>>", this.$route);
// 判断当前路由的path是index时,返回,不执行储存路由到vuex中去
if (this.$route.path == '/index') return;
// 调用vuex中的添加方法
this.$store.dispatch("addTag", this.$route);
}
}
};
</script>
<style lang="scss" scoped>
.tagwrap {
margin-bottom: 20px;
// padding: 10px 0;
// background: red;
}
.routerlink {
height: 30px;
padding: 7px 15px;
background-color: #f3f7f3;
text-decoration: none;
margin: 0 5px;
font-size: 14px;
color: black;
&:hover {
background-color: rgb(0, 180, 0);
color: white;
}
}
// 设置点击tag后的样式
.active {
background-color: rgb(0, 180, 0);
color: white;
border-radius: 5px;
}
.tagViewBg {
padding: 10px 0;
background: red;
}
</style>>
- 状态管理tagList
// tagList.js
import { saveTagToCookie, deleteAllTagFromCookie } from "@/common/cookieTag.js";
// import { , getTagFromCookie } from "@/common/cookieTag.js";
export const Tag = {
state: {
tagList: []
},
mutations: {
// 将传进来的tag添加到tagList中
ADD_Tag(state, tag) {
/**
* 点击tag时,去重处理
* 1. 用some函数去判断当前点击的tag是否在数组中存在,只要有一项满足条件,将返回true
*/
console.log("state.tagList", state.tagList);
const isResult = state.tagList.some(item => {
return item.path == tag.path;
})
// 2. 判断当isResult为真的时候返回,为假的时候执行下面push的代码
if (isResult) return;
/**
* 3. 在将传进来的标签json对象进行cookie持久化存储的时候,因为标签json对象里面有一些数组,就会遇到不能将json数据转换成字符串的错误
* 取出tag标签json对象中我们需要的值存放到一个新json数组中,将新的json数组添加到state中的tagList
* */
const newTagArr = {
name: tag.name,
path: tag.path,
title: tag.meta.title
}
state.tagList.push(newTagArr);
// 4. 将tagList存放到cookie中进行持久化存储
saveTagToCookie(state.tagList);
},
// 删除tag时,对传进来的tag值进行判断,若该值存在,就将其删除
DELETE_Tag(state, tag) {
// 在vuex中将一个tag数据从tag数组中删除
for (let i = 0; i <= state.tagList.length; i++) {
if (state.tagList[i] == tag) {
state.tagList.splice(i, 1);
break;
}
}
// 将删除tag数据后的state.tagList在存储一遍
saveTagToCookie(state.tagList);
},
DELETE_ALL_TAG(state) {
state.tagList = [];
deleteAllTagFromCookie();
}
},
actions: {
addTag({ commit, state }, tag) {
console.log("state.tagList<<<<<<<<<<<<", state.tagList);
commit('ADD_Tag', tag);
},
deleteTag({ commit, state }, tag) {
/**
* 1. 利用promise异步处理,避免取vuex中的数据时,会取到旧的数据
* 2. 将vuex中state存储的数据传进来
* 3. 当外部调用删除tag标签方法时,进行完删除操作后tagList数组的数据会更新
* 4. 将更新的数据展开copy一份,避免直接操作state存储的数据
* 5. 将copy的数据数据交给resolve处理,并返回
* 6. resolve处理成功的数据
*/
return new Promise((resolve, reject) => {
commit('DELETE_Tag', tag);
resolve([...state.tagList]);
})
},
deleteAllTag({ commit }) {
commit('DELETE_ALL_TAG');
}
}
}
1. 首先watch侦听器侦听路由的变化,当路由变化时,将当前路由对象保存到vuex当中去

2. 在vuex状态管理中有个tagList存放路由变化的tag,在vuex里面去处理去重问题,判断当前点击的路由不存在的时候,才将新的路由添加到tag数组中,并将tag数组进行持久化存储,解决一刷新tag标签就消失的问题

3. 用computed计算属性去监听从vuex状态管理中去获取到的值,在页面渲染出来
1)监听状态管理并返回一个tagList数组

2) 在页面渲染遍历出来

4. 判断tag标签的点击状态,设置不同的css样式
1)判断点击的tag标签的路由路径是否是当前路由this.$route.ptah的路径,返回true或false

2) 三目运算符设置不同css样式

5. 点击关闭按钮关闭标签,
1)传入点击的tag标签的路由,从vuex状态管理中去删除一个点击的路由数组项,在vuex中有异步处理



2)关闭一个tag标签时,tag的选中状态转换到最后一个tag标签,页面跳转到最后一个tag标签的页面;若关闭的是最后一个tag标签,则跳转的index首页

