面包屑 + Tag標簽切換功能
有關后台管理系統之前寫過兩遍博客,看這篇之前最好先看下這兩篇博客。另外這里只展示關鍵部分代碼,項目代碼放在github上: mall-manage-system
1、Vue + Element-ui實現后台管理系統(1) --- 總述
2、Vue + Element-ui實現后台管理系統(2)---項目搭建 + ⾸⻚布局實現
這篇主要講解 面包屑 + Tag標簽切換功能:
整體效果


說明
從上面圖片可以看出,面包屑是在head部分組件里,Tag標簽雖然不再head部分組件里,但是它在整個管理后台系統中是會一直存在的,所以需要在Main.vue中。
這兩塊功能的實現,主要依賴Element-ui兩個樣式 Breadcrumb 面包屑 + Tag 標簽
一、面包屑功能
1、背景
整個大致邏輯是這樣的,首先是面包屑 首頁
一定要存在的,接下來 側邊組件 點擊某菜單,把這個數據存到vuex中,然后 頭部組件 來獲取vuex中這個數據並展示。
2、CommonAside(側邊欄)
側邊欄需要做的就是當click當前菜單 就要把這個數據存儲到vuex中,為了頭部組件來獲取展示這份數據。
這里定義了一個click事件
methods: {
//跳轉路由 根據名稱跳轉
clickMenu(item) {
//調用vuex的selectMenu方法存儲數據
this.$store.commit('selectMenu', item)
//跳轉路由
this.$router.push({ name: item.name })
}
}
3、CommonHeader(頭部組件)
因為面包屑是寫在CommonHeader中,所以這里展示這部分代碼
<el-breadcrumb separator-class="el-icon-arrow-right">
<!--很明顯 首頁 一定是存在的 所以這里直接寫死-->
<el-breadcrumb-item :to="{ path: '/' }">首頁</el-breadcrumb-item>
<!--第二級菜單名稱 就要看左側組件有沒有點擊指定菜單,沒有那就只顯示首頁 點擊就顯示當前菜單名稱-->
<el-breadcrumb-item :to="current.path" v-if="current" >{{current.label}}</el-breadcrumb-item>
</el-breadcrumb>
<script>
//js部分
import { mapState } from 'vuex'
export default {
computed: {
//獲取vuex數據的另一種寫法
...mapState({
current: state => state.tab.currentMenu
})
}
}
</script>
4、vuex配置
這里用了一個屬性為 currentMenu 的來存儲當前菜單信息
state: {
//當前菜單
currentMenu: null,
},
mutations: {
selectMenu(state, val) {
//如果點擊應該是首頁的話 要把這份數據清空 因為頭部組件已經把首頁寫死了 只有點擊不是首頁菜單才存儲當前菜單
val.name === 'home' ? (state.currentMenu = null) : (state.currentMenu = val)
}
},
}
這樣整個面包屑的功能就是實現了。
二、Tag標簽切換功能

1、背景
從上面效果來看,我們發現:
1、首頁的tag一開始就會存在,而且是不能進行刪除的
2、當點擊左側欄的時候,如果tag沒有該菜單名稱則新增,如果已經有了那么當前tag背景為藍色。
3、刪除當前tag,如果是最后一個,那么路由調整到它前面那個標簽並且背景變藍,如果不是最后一個那么路由調整到它后面那個標簽並且背景變藍。
4、還有我們注意這個tag不論路由如何切換都是會存在的,所以這個tag一定要存在我們之前定義的Main.vue中。
2、CommonTab.vue(標簽組件)
<template>
<div class="tabs">
<!--closable這里說明home是不能關閉的-->
<el-tag
:key="tag.name"
size="small"
v-for="(tag, index) in tags"
:closable="tag.name !== 'home'"
:disable-transitions="false"
@close="handleClose(tag, index)"
@click="changeMenu(tag)"
:effect="$route.name === tag.name ? 'dark' : 'plain'"
>
{{ tag.label }}
</el-tag>
</div>
</template>
<script>
import { mapState, mapMutations } from 'vuex'
export default {
computed: {
//獲取vuex的標簽集合數據
...mapState({
tags: state => state.tab.tabsList
})
},
methods: {
...mapMutations({
close: 'closeTab'
}),
//關閉標簽
handleClose(tag, index) {
let length = this.tags.length - 1
//vuex調方法的另一種寫法
this.close(tag)
// 如果關閉的標簽不是當前路由的話,就不跳轉
if (tag.name !== this.$route.name) {
return
}
// 關閉的標簽是最右邊的話,往左邊跳轉一個
if (index === length) {
this.$router.push({ name: this.tags[index - 1].name })
} else {
// 否則往右邊跳轉
this.$router.push({ name: this.tags[index].name })
}
},
//選擇標簽跳轉路由
changeMenu(item) {
this.$router.push({ name: item.name })
this.$store.commit('selectMenu', item)
}
}
}
</script>
3、vuex配置
export default {
//存儲數據
state: {
currentMenu: null,
tabsList: [
{
path: '/',
name: 'home',
label: '首頁',
icon: 'home'
}
]
},
//調用方法
mutations: {
//選擇標簽 選擇面包屑
selectMenu(state, val) {
if (val.name === 'home') {
state.currentMenu = null
} else {
state.currentMenu = val
//如果等於-1說明tabsList不存在那么插入,否則什么都不做
let result = state.tabsList.findIndex(item => item.name === val.name)
result === -1 ? state.tabsList.push(val) : ''
}
// val.name === 'home' ? (state.currentMenu = null) : (state.currentMenu = val)
},
//關閉標簽
closeTab(state, val) {
let result = state.tabsList.findIndex(item => item.name === val.name)
state.tabsList.splice(result, 1)
},
},
actions: {}
}
4、Main.vue(主組件)
既然tag在整個后台都要顯示,那么就需要將CommonTab.vue加入到Main.vue中。
<template>
<el-container style="height: 100%">
<el-aside width="auto">
<common-aside></common-aside>
</el-aside>
<el-container>
<el-header>
<common-header></common-header>
</el-header>
<!--加入CommonTab-->
<common-tab></common-tab>
<el-main>
<router-view/>
</el-main>
</el-container>
</el-container>
</template>
具體的看完整項目吧,最上面已經給了github地址了。
別人罵我胖,我會生氣,因為我心里承認了我胖。別人說我矮,我就會覺得好笑,因為我心里知道我不可能矮。這就是我們為什么會對別人的攻擊生氣。
攻我盾者,乃我內心之矛(14)