vue動態面包屑路由組件實現,無污染、易配置
這幾天開發一個vue項目,因為頁面非常多,而且有面包屑需求
開始想法:<適用于有面包屑的頁面少的情況> 每個頁面用vue路由傳參實現,每次跳轉傳參,頁面根據參數設置面包屑路由;
后來想法:規劃好路由,將路由和面包屑一一對應起來,頁面加載后解析路由,組合成面包屑即可(如下圖),路由的名稱是對應起來添加到配置中
下面是我的兩種思路和組件實現(至于面包屑的樣式實現并不難,這里直接用elemetUI組件的,我主要是說動態面包屑思路,并不是面包屑樣式,如果UI組件不同,只需要自己做一些簡單修改即可):
實現:
breadBox1.0.vue:
<!--
v1.0
breadBox 路由配置好,面包屑直接對應
-->
<template>
<div class="breadEval">
<div class="breadTitle">
<el-breadcrumb separator="/">
<el-breadcrumb-item>您的位置:</el-breadcrumb-item>
<el-breadcrumb-item :to="item.path" v-for="item of breadListLast" :key="item.path">
{{item.name}}
</el-breadcrumb-item>
</el-breadcrumb>
</div>
<router-view></router-view>
</div>
</template>
<script>
export default {
//面包屑解決方案,此方法只適用于面包屑與路由顯示順序一致,例如path:01/02/03 面包屑也是01/02/03
data() {
return {
//手動配置項:breadListIm為路由與面包屑名稱對應關系,breadLoadName為面包屑組件路由
breadLoadName: '/breadBox',
breadListIm: [
{
path: '01',
name: '一級'
},
{
path: '02',
name: '二級'
},
{
path: '03',
name: '三級'
},
],
breadListLast: []
};
},
methods: {
loadChange() {
this.breadListLast = []
if (this.$route.path.indexOf(this.breadLoadName) === -1) {
console.log('面包屑路由地址breadLoadName沒有配置正確!')
} else {
let breadListAgo = this.$route.path.split(this.breadLoadName)
// let breadListAgo = '/index/indexSchool/breadList/01/02/03'.split(this.breadLoadName)
let breadList = breadListAgo[1].split('/')
let obje = {}
let breadIndex = ''
//刪除掉數組的前1個,提升遍歷性能
breadList.splice(0, 1)
//考慮到順序問題,只能先遍歷breadList,再遍歷breadListIm
for (let p of breadList) {
for (let q of this.breadListIm) {
if (p === q.path) {
breadIndex += '/' + q.path
obje.path = breadListAgo[0] + this.breadLoadName + breadIndex
obje.name = q.name
this.breadListLast.push(obje)
obje = {}
}
}
}
// 打印路由配置
// console.log(JSON.stringify(this.breadListLast))
}
}
},
watch: {
$route(to, from) {
this.loadChange()
// console.log(to.path);
}
},
//頁面掛載之后,解析路由,給出面包屑,路由里面一定要含有breadCom組件的path
mounted: function () {
this.loadChange()
}
};
</script>
<style lang="scss" scoped>
.breadEval {
position: relative;
font-size: 14px;
height: 100%;
background: #F3F7FD;
.breadTitle{
padding: 20px 30px;
background: #fff;
}
}
</style>
優點:插拔輕松,容易配置(樣式現在基于elementUI,完全可以改成任意面包屑組件)
直接將breadBox放在 router/index.js 的路由中間即可,當然,上一層組件模塊要加上 <router-view></router-view>
image.png
v1.0效果
最后:上面的思路親測可行,配合vue-router的path和redirect用的不錯,但考慮到可能會出現重復路由配置過多,又寫了一版兼容開始的想法,
當然這次吸取教訓,將配置路由也提了出來。
更適合于路由沒有規劃的項目,拿來即用。
breadBox2.0.vue:
<!--
breadBox v2.0 說明:1.0和2.0選擇一種方法配置動態路由即可
1.0 breadBox 面包屑跟隨路由變化,此方法需要面包屑與路由顯示順序一致,例如path:01/02/03 面包屑也是01/02/03,
2.0 增加路由參數配置項,動態面包屑,面包屑跟隨參數變化
(2.0方法雖然萬能,但在頁面過多的時候不推薦,每次路由跳轉帶上面包屑參數會造成麻煩
2.0推薦使用情況:在路由和面包屑根本對不上,重定向也不好用的時候,或者重復路由配置過多的,或者僅一兩個頁面有面包屑又想引入此組件的)
優點:插拔輕松,容易配置(樣式基于elementUI)
-->
<template>
<div class="breadEval">
<div class="breadTitle">
<el-breadcrumb separator="/">
<el-breadcrumb-item>您的位置:</el-breadcrumb-item>
<el-breadcrumb-item :to="item.path" v-for="item of breadListLast" :key="item.path">
{{item.name}}
</el-breadcrumb-item>
</el-breadcrumb>
</div>
<router-view></router-view>
</div>
</template>
<script>
export default {
//面包屑解決方案,
data() {
return {
//v1.0手動配置項:breadListIm為路由與面包屑名稱對應關系,breadLoadName為面包屑組件路由
//v2.0手動配置項:breadListParam為路由與面包屑名稱對應關系,breadBoxIdName為路由參數名
breadLoadName: '/breadBox',
breadListIm: [
{
path: '01',
name: '一級'
},
{
path: '02',
name: '二級'
},
{
path: '03',
name: '三級'
},
],
breadListParam:{
"1":[{path:"/home/01",name:"一級01"},
{path:"/home/02/01",name:"二級01"},
{path:"/home/03/02/01",name:"三級01"}],
"2":[{path:"/home/01",name:"一級02"},
{path:"/home/02/01",name:"二級02"},
{path:"/home/03/02/01",name:"三級02"}]
},
breadBoxIdName:'breadBoxId',
breadListLast: [],
};
},
methods: {
loadChange() {
this.breadListLast = []
//獲取參數breadBoxId值
let breadBoxId = this.$route.query[this.breadBoxIdName]
console.log(breadBoxId)
if( undefined == breadBoxId || breadBoxId == null || '' == breadBoxId ){
if (this.$route.path.indexOf(this.breadLoadName) === -1) {
console.log('面包屑路由地址breadLoadName沒有配置正確!')
} else {
let breadListAgo = this.$route.path.split(this.breadLoadName)
// let breadListAgo = '/index/indexSchool/breadList/01/02/03'.split(this.breadLoadName)
let breadList = breadListAgo[1].split('/')
let obje = {}
let breadIndex = ''
//刪除掉數組的前1個,提升遍歷性能
breadList.splice(0, 1)
//考慮到順序問題,只能先遍歷breadList,再遍歷breadListIm
for (let p of breadList) {
for (let q of this.breadListIm) {
if (p === q.path) {
breadIndex += '/' + q.path
obje.path = breadListAgo[0] + this.breadLoadName + breadIndex
obje.name = q.name
this.breadListLast.push(obje)
obje = {}
}
}
}
};
}else{
this.breadListLast = this.breadListParam[breadBoxId]
}
// 打印路由配置
console.log(JSON.stringify(this.breadListLast))
}
},
watch: {
$route(to, from) {
this.loadChange()
// console.log(to.path);
}
},
//頁面掛載之后,解析路由,給出面包屑,路由里面一定要含有breadCom組件的path
mounted: function () {
this.loadChange()
}
};
</script>
<style lang="scss" scoped>
.breadEval {
position: relative;
font-size: 14px;
height: 100%;
background: #F3F7FD;
.breadTitle{
padding: 20px 30px;
background: #fff;
}
}
</style>
V2.0效果