简单的来说,面包屑导航的作用就是告诉用户他们在网站中的位置,方便用户确定下一步去留,对于用户来说这是很好的体验。
静态路由-面包屑导航
需要手动配置路由和菜单。
项目路由如下
const routes = [
{
path: '/home1',
name: 'home1',
meta: {
breadID: '0'
}
},
{
path: '/home2',
name: 'home2',
meta: {
breadID: '0-0'
}
},
{
path: '/home3',
name: 'home3',
meta: {
breadID: '0-0-0'
}
},
{
path: '/home4',
name: 'home4',
meta: {
breadID: '1'
}
},
{
path: '/home5',
name: 'home5',
meta: {
breadID: '1-0'
}
},
{
path: '/home6',
name: 'home6',
meta: {
breadID: '1-0-0'
}
}
]
菜单配置如下
面包屑导航有一个层级的菜单。
let breadNavList = [
{
id:"0",
name:'0-第一级',
url:'/home1',
menu:[
{
id:'0-0',
name:'0-第二级',
url:'/home2',
menu:[
{
id:'0-0-0',
name:'0-第三级',
url:'/home3',
}
]
}
]
},
{
id:"1",
name:'1-第一级',
url:'/home3',
menu:[
{
id:'1-0',
name:'0-第二级',
url:'/home4',
menu:[
{
id:'1-0-0',
name:'0-第三级',
url:'/home5',
}
]
}
]
}
]
可以看到在路由的meta字段中加入了属性breadID,详情解说一下这个属性
breadID表明当前路由在menu菜单中的位置。
'0' 当前面包屑有一级,0代表该路由在在菜单栏中的位置breadNavList[0]
'0-0' 代表当前面包屑有两级,breadNavList[0].menu[0]
'0-0-0' 代表当前面包屑有三级,breadNavList[0].menu[0].menu[0]
'0-1-0' 代表当前面包屑有三级,breadNavList[0].menu[1].menu[0]
.....以此类推
实现
实现一个容器
数组bread用来装载需要展现的路由。如:
bread = ['第一级','第二级','第三级']
bread = ['第一级','第二级']
效果:
第一级 > 第二级 > 第三级
第一级 > 第二级
监听路由变化
当路由变化的时候,面包屑也会发生变化。
- 判断当前是否有路由
- 判断当前路由是否有字段breadID
- 如若有,调用getBread函数递归获取面包屑
watch:{
'$route':{
handler(){
this.bread = []
if(this.$route && this.$route.meta && this.$route.meta.breadID){
let arr = this.$route.meta.breadID.split('-')
this.getBread(arr,this.breadNavList)
} else {
console.error('字段`this.$route.meta.breadID`没有设置')
}
},
immediate:true
}
}
递归获取面包屑
getBread参数:
- 当前路由属性breadID,转化成数组arr,如:'0-1-0' -> ['0','1','0']
- 菜单menu,当前层级下的菜单。
思路:
- 获取arr的长度,如果小于0,说明这个层级不存在,不往下递归。
- 如果大于0,说明层级存在,将这一层的name以及url加入容器bread。
- 取出arr第一个元素。
- 循环第一,二,三步,直到arr的长度为0。
getBread(arr,menu){
if(arr.length < 0){
return;
}
this.bread.push(menu[arr[0]])
menu = menu[arr[0]].menu
arr.shift()
this.getBread(arr,menu)
}
全部代码
<template>
<div class="bread-wrap">
<div class="bread-item" v-for="(item,index) in bread" :key="index">
<span @click="toBreadRouter(item)">{{item.name}}</span><i v-if="index !== bread.length - 1"> > </i></div>
</div>
</template>
<script>
export default {
name: "breadNav",
data() {
return {
bread:[],//面包屑容器
breadNavList:[]// 面包屑菜单
}
},
watch:{
'$route':{
handler(){
this.bread = []
if(this.$route && this.$route.meta && this.$route.meta.breadID){
let arr = this.$route.meta.breadID.split('-')
this.getBread(arr,this.breadNavList)
} else {
console.error('字段`this.$route.meta.breadID`没有设置')
}
}
}
},
methods: {
getBread(arr,menu){
if(arr.length > 0){
this.bread.push(menu[arr[0]])
menu = menu[arr[0]].menu
arr.shift()
if(arr.length > 0){
return this.getBread(arr,menu)
}
}
},
toBreadRouter(item){
this.$emit('changeRoute',item)
}
}
}
</script>
<style scoped>
.bread-wrap{
color:#606266;
font-size:14px;
}
.bread-wrap .bread-item{
display: inline-block;
}
.bread-wrap .bread-item span:hover{
cursor: pointer;
color:#409EFF;
}
.bread-wrap .bread-item:last-child{
cursor: auto;
color:#303133;
}
.bread-wrap .bread-item:last-child span{
cursor: auto;
}
.bread-wrap .bread-item i{
font-style: normal;
}
</style>
demo演示

缺点
- 路由的breadID必须和menu菜单的子项位置一一对应。
- 如果项目中有两个面包屑,路由的breadID将会混乱。
- 不适用一个产品可能属于多个类目的项目。(也就是说你根据不同的类目路径进行点击都可能得到同一个产品。)
总结
该面包屑组件封装上了npm有兴趣的可以下载试试看。gitHub地址-面包屑导航使用教程