一步步创建一个vue项目(五)标签栏
实现根据route内容实现标签栏
这里是依据vue-element-admin中的代码,通过自己整理后将自己整理的一些内容列出来:
首先是要实现的功能:
1.点击左面的导航栏右面会出现相对应的标签和页面(可关闭)
2.判断页面是否活跃,哪些页面是活跃状态
目前只实现了这两个功能
这里的标签页的记录使用了store,把哪些页面打开,哪些页面关闭使用store记录,主要代码以及注释我都标了出来:
首先在store里创建一个值用来存路由的状态:visitedViews
然后是标签页的页面:
//TabsView.vue
<template>
<div class="tabs-view-container">
<router-link
class="tabs-view"
v-for="tag in Array.from(visitedViews)"
:to="tag.path"
:key="tag.path"
>
<el-tag
:closable="true"
:class="isActive(tag.path) ? 'active' : ''"
@close.prevent="closeViewTabs(tag, $event)"
>
{{ tag.name }}
</el-tag>
</router-link>
</div>
</template>
<script>
export default {
data () {
return {}
},
created () {
this.addViewTabs()
},
computed: {
// 获取当前的路由
visitedViews () {
return this.$store.state.app.visitedViews.slice(-6)
}
},
methods: {
closeViewTabs (view, $event) {
this.$store.dispatch('delVisitedViews', view)
// 判断删掉的元素是否是当前正在浏览的页面
if (this.isActive(view.path)) {
// 切换活跃页面
this.toLastView(this.visitedViews, view)
}
},
generateRoute () {
if (this.$route.matched[this.$route.matched.length - 1].name) {
return this.$route.matched[this.$route.matched.length - 1]
}
this.$route.matched[0].path = '/'
return this.$route.matched[0]
},
addViewTabs () {
this.$store.dispatch('addVisitedViews', this.generateRoute())
},
isActive (path) {
return path === this.$route.path
},
toLastView (visitedViews, view) {
// slice()方法截取某个范围的数组的元素
// 比如slice(1,3),数组从0开始,包前不包后截取两个数,负数从后往前数
// 这里是截取最后一个元素
// 截取最后一个元素,也就是关闭页面后当前活跃页
console.log(view)
const latestView = visitedViews.slice(-1)[0]
console.log(latestView)
// 如果存在最后一页
if (latestView) {
this.$router.push(latestView.path)
} else {
// 否则显示默认页
if (view.name === '首页') {
// 重定向首页
this.$router.replace({ path: view.path })
} else {
this.$router.push('/')
}
}
}
},
watch: {
$route () {
this.addViewTabs()
}
}
}
</script>
<style rel="stylesheet/scss" lang="scss" scoped>
.tabs-view-container {
display: inline-block;
vertical-align: top;
margin-left: 10px;
.tabs-view {
margin-left: 10px;
}
}
.active {
background-color: #42b983;
color: #fff;
border-color: #42b983;
&::before {
content: "";
background: #fff;
display: inline-block;
width: 8px;
height: 8px;
border-radius: 50%;
position: relative;
margin-right: 2px;
}
}
</style>
在想引入的页面中引入后就是store里面写一些增加和删除的功能:
//app.js
// 标签栏
const app = {
state: {
visitedViews: []
},
mutations: {
// 添加tab
ADD_VISITED_VIEWS: (state, view) => {
// 判断添加的tab如果路径已经存在则return
if (state.visitedViews.some(v => v.path === view.path)) return
// 否则添加
state.visitedViews.push({ name: view.name, path: view.path })
},
// 删除tab
DEL_VISITED_VIEWS: (state, view) => {
// entries()方法返回数组中的每一项键值对
// splice()方法添加或删除,格式splice(i,i,obj,obj···),前两个是两个数字,后面是元素,第一个数字代表从第几个删除或添加,第二个数字代表删除几个元素
// 两个数字后面的元素代表添加这些元素,返回值是被删除掉的元素
for (const [i, v] of state.visitedViews.entries()) {
if (v.path === view.path) {
// 返回被删掉的数组元素
state.visitedViews.splice(i, 1)
break
}
}
}
},
actions: {
addVisitedViews: ({ commit }, view) => {
commit('ADD_VISITED_VIEWS', view)
},
delVisitedViews: ({ commit }, view) => {
commit('DEL_VISITED_VIEWS', view)
}
}
}
export default app
主要的思路应该就是通过点击侧边栏后路由会发生变化,然后将发生变化的路由(增加或者减少的)记录在store中的数组,将数组拆开就是各个标签,将拆开后的每一项进行删除就实现了删除标签。