Lenny-Hu / note

blog
5 stars 1 forks source link

vue面包屑导航:基于$route.matched #3

Open Lenny-Hu opened 5 years ago

Lenny-Hu commented 5 years ago

特点

组件代码

<template>
  <dl class="breadcrumb">
    <dt>我的位置 : </dt>
    <dd v-for="(v, i) in list" :key="i">
      <router-link :class="{'active': v.active}" :to="v.path">{{ v.title }}</router-link>
    </dd>
  </dl>
</template>

<script>
const parseParams = (paramsMap, paramKeys, hash, data) => {
  let result = { path: data.path, title: data.title } // 只提取有用的,同时修改了路由对象
  if (paramKeys.length) {
    paramKeys.forEach((k) => {
      result.path = result.path.replace(k, paramsMap[k])
    })
    let pos = hash.indexOf(result.path)
    pos !== -1 && (result.path = hash.slice(0, pos + result.path.length))
  }
  return result
}

const parseBreadcrumb = (item) => {
  let breadcrumb = item.meta.breadcrumb
  if (!(breadcrumb && breadcrumb.title && breadcrumb.path)) {
    return null
  }
  return breadcrumb
}

export default {
  name: 'breadcrumb',
  computed: {
    list () {
      let map = {}
      let paramsMap = {}
      let hash = window.location.hash.slice(1)
      let n = 0
      let results = []

      Object.keys(this.$route.params).forEach((k) => {
        paramsMap[`:${k}`] = this.$route.params[k]
      })
      let keys = Object.keys(paramsMap)
      let addResult = (data) => {
        // 重复:后面的覆盖前面的
        if (map[data.title]) {
          let _i = map[data.title].index
          results[_i] = data
        } else {
          results.push(data)
          map[data.title] = { index: n }
          n++
        }
      }

      this.$route.matched.forEach((item, index) => {
        if (item.meta.title) {
          let data = { title: item.meta.title, path: item.path }

          // 解析:id/:id这种动态路由
          data = parseParams(paramsMap, keys, hash, data)

          // 读取同级路由的面包屑配置(这儿配置的是面包屑中的上一级)
          let breadcrumb = parseBreadcrumb(item)
          if (breadcrumb) {
            addResult(parseParams(paramsMap, keys, hash, breadcrumb))
          }

          addResult(data)
        }
      })

      results[results.length - 1].active = true
      return results
    }
  }
}
</script>

路由

[
  {
    path: '/tutor',
    name: 'tutor',
    component: TutorIndex,
    // redirect: '/tutor/home',
    beforeEnter: auth,
    children: [
      {
        path: 'info',
        name: 'tutor.info',
        component: TutorInfo,
        // redirect: '/tutor/home',
        meta: {
          title: '我的信息',
          icon: 'my_information'
        }
      },
      {
        path: 'course',
        name: 'tutor.course',
        component: TutorCourse,
        redirect: '/tutor/course/mine',
        meta: {
          title: '我的研学',
          icon: 'my_research'
        },
        children: [
          {
            path: 'mine',
            name: 'tutor.course.mine',
            component: TutorCourseMine,
            meta: {
              title: '我的研学'
            }
          },
          {
            path: ':sn',
            name: 'tutor.course.detail',
            component: TutorCourseDetail,
            meta: {
              title: '课程详情'
            }
          },
          {
            path: ':sn/student',
            name: 'tutor.course.student',
            component: TutorCourseStudent,
            meta: {
              title: '评价学生'
            }
          },
          {
            path: ':sn/student/:ucMainid/comment/',
            name: 'tutor.course.student.comment',
            component: TutorCourseComment,
            meta: {
              title: '写评价',
              breadcrumb: { // 配置面包屑前一级
                title: '评价学生',
                path: ':sn/student'
              }
            }
          }
        ]
      },
      {
        path: 'message',
        name: 'tutor.message',
        component: TutorMessage,
        meta: {
          title: '站内信',
          icon: 'message'
        }
      }
    ]
  }
]

使用

<breadcrumb/>