前言:最近在写一个基于element + vue 技术的pc端外卖管理系统项目,其中主内容头部区域用到了面包屑的效果,面包屑的文字内容和点击文字跳转到对应得组件页面,要根据路由信息动态生成。在这里呢,将实现思路做个记录。
一、先来看看element上面的面包屑模板
<el-breadcrumb separator-class="el-icon-arrow-right">
<el-breadcrumb-item :to="{ path: '/' }">首页</el-breadcrumb-item> //这个to属性是我们在点击首页时会跳转到首页组件
<el-breadcrumb-item>活动管理</el-breadcrumb-item>
<el-breadcrumb-item>活动列表</el-breadcrumb-item>
<el-breadcrumb-item>活动详情</el-breadcrumb-item>
</el-breadcrumb>
二、由于我们的面包屑是要动态获取数据生成,所以不能像上面那样写死,那这个时候我们需要两个变量,一个变量代表点击文字跳转对应组件的to属性,另一个代表显示的文字内容(title),比如:首页、活动管理。
接下来就定义一个空对象数组
//我们要的对象数组的数据格式应该是下面这样,但是数组里面的内容是后面动态计算生成,所以先定义空数组
//breads:[
// {to:'/account',title:'账号管理'},
// {to:'/account/add',title:'账号添加'}
//]
export default {
data() {
return {
breads: [], //定义面包屑数组
}
}
}
三、删除面包屑多余子项,用v-for遍历breads对象数组,动态生成面包屑子项
<el-breadcrumb separator-class="el-icon-arrow-right">
<el-breadcrumb-item
v-for="bread in breads"
:key="bread.title"
:to="bread.to"> //动态绑定点击跳转路径
{{ bread.title }} //动态绑定文字内容
</el-breadcrumb-item>
</el-breadcrumb>
四、接下来来了解一下路由信息对象(this.$route)下的matched对象数组,它包含当前路由的所有嵌套路径片段的路由记录,可以用它拿到当前路由的path,那to值就有了,而matched下面每个对象里都有一个meta属性,它是元信息,可以在里面添加我们需要的数据,那title就可以添加在里面
meta需要在项目目录router/index.js里面配置
//订单管理
{
path: '/order',
component: Layout,
meta: { title: '订单管理' }, //配置自己的meta
children: [
{
path: '',
component: Order
}
]
},
//商品管理
{
path: '/goods',
component: Layout,
meta: { title: '商品管理' }, //配置自己meta
redirect: '/goods/list',
children: [
{
path: '/goods/list',
component: GoodsList,
meta: { title: '商品列表' } //配置子菜单的meta
},
{
path: '/goods/add',
component: GoodsAdd,
meta: { title: '商品添加' } //配置子菜单的meta
},
{
path: '/goods/category',
component: GoodsCategory,
meta: { title: '商品分类' } //配置子菜单的meta
}
]
},
五、写计算面包屑的函数
----------------------------------------------------------------------------------------
// 配置后打印this.$route.matched
//点击'订单管理'导航项(没有子菜单的页面)
matched:[
0:{path:'/order',xxx,...,meta{title:'订单管理'},xxx,...} //存放父导航项信息
1:{path:'/order',xxx,...,meta{},xxx,...} //存放子导航项信息
]
//点击'账号添加'导航项(有子菜单的页面)
matched:[
0:{path:'/account',xxx,...,meta{title:'账号管理'},xxx,...} //存放父导航项信息
1:{path:'/account/add',xxx,...,meta{title:'账号添加'},xxx,...} //存放子导航项信息
]
----------------------------------------------------------------------------------------
实现的代码:
methods:
{
//计算面包屑
calcBreads() {
//让每一页都可以跳转首页
let temp = [{ to: "/home", title: "首页" }];
let r = this.$route.matched
.filter((v) => v.meta.title) //当点击的是没有子菜单的导航项时,过滤掉matched对象数组中的第二项
.map((v) => {
return { to: v.path, title: v.meta.title }; //提取path和title生成我们需要的数据格式
});
this.breads = [...temp, ...r]; //让面包屑以首页开头 => 首页 / 账号管理 / 账号添加
}
},
created() {
//页面刷新时要调用计算面包屑函数
this.calcBreads();
},
六、以上方法只有点击导航项时,重新刷新页面后面包屑才正确显示内容。直接点击切换导航项,面包屑的内容显示是不对的,那这个时候需要监听路由路径的变化,调用计算面包屑函数重新计算
// 侦听器
watch: {
//页面不刷新的话面包屑的显示文字不会改变,所以要监听路由路径的值状态
//监听到路由地址变了(点击菜单)也要调用计算面包屑的函数重新计算
"$route.path"() {
this.calcBreads();
},
},
七、当我们在当前组件页面连续点击当前面包屑导航,浏览器会有警告,在项目目录router/index.js重写路由的push就可以消除警告了
// 重写路由的push 解决跳转当前导航的警告
const originPush = VueRouter.prototype.push
VueRouter.prototype.push = function (location) {
return originPush.call(this, location).catch(err => err)
}