前言:最近在写一个基于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)
}