前端菜单和路由

菜单

  1. 直接前端写死菜单
  2. 根据路由来渲染

路由

  1. 前端直接写死
  2. 后端返回

根据路由渲染的菜单怎么区分哪些是菜单

前端直接写死

在写路由的时候可以加上属性 hidden: true
如果 hidden是true的时候我们就不把这个路由显示为菜单

{
    path: '/enterprise',
    component: Layout,
    name: 'enterprise',
    meta: { title: '企业管理', icon: 'product' },
    children: [{
      path: 'information',
      name: 'information',
      component: () => import('@/views/enterprise/information'),
      meta: { title: '企业信息' },
      hidden: false
    },
    {
      path: 'detail',
      name: 'detail',
      component: () => import('@/views/enterprise/detail'),
      meta: { title: '新增企业' },
      hidden: true
    },
    ]
}

后端返回(大多数情况也后端返回的)

  1. 后端返回的话就会有个菜单管理,我们可以新增菜单和配置菜单的地址和我们前端组件的相对地址
  2. 后端返回的数据也有两种格式(1.直接返回菜单树 2.返回的是一维数组,这时候我们需要根据id和pid的关系处理成菜单树)
  3. 需要使用递归生成路由表
    // 处理路由
    const loadView = (url) => {
      // 路由懒加载
      return (resolve) => require([`@/views${url}`], resolve)
    }
    
    // 这个方法返回的结果是一个路由表  跟你手写的路由表是一样的  我这里删除了一些其他的逻辑  只留了主要逻辑  不能拿到其他项目使用!!!
    function settingUpDynamicRouting(data) {
      const res = []
      for (let i = 0; i < data.length; i++) {
        const obj = {}
        if (data[i].children && data[i].children.length > 0) {
          if (data[i].extend.type === 1) { // 这里根据type === 1 来判断是布局组件还是布局页面下的二级路由 (每个项目判断的方式都不一样,看你们公司怎么判断,而且每个项目也都不一样,你明白原理就行)
            obj.children = settingUpDynamicRouting(data[i].children)
            obj.component = Layout // Layout这个是布局组件,你也可以理解为一级路由
          } else if (data[i].extend.type === 2) {  // type === 2  是二级路由,就是布局页面下展示的页面
            obj.component = loadView(data[i].extend.path) // loadView()  通过这个方法动态获取组件
          }
        }
        res.push(obj)
      }
      return res
    }
    
    // 最后需要通过router.addRoutes()方法把我们要添加的路由加进去。  (这句话可以不管:这里是我们现在常用的vue-router的方法  最新版本的好像是改名字了  但是用法是一样的)
    router.beforeEach(async(to, from, next) => { // async 你能理解的话就看,要是不懂的话就不管。这个也可以不要,可以后面学学
      const hasToken = getToken()
      if (hasToken) { // 登录了
        if (store.getters.menuList.length > 0) { // 有路由信息,我这里请求的时候也存到了vuex,因为vuex里面的数据刷新以后就没有了,所以刷新页面以后是会重新请求的
            next()
          } else { // 没有路由信息,就重新去请求
            store
              .dispatch('user/getMenu', userInfo.id) // 处理路由数据的方法我放到vuex里面去做了,所以这个方法返回的是直接可以使用的路由表
              .then((res) => {
                // 获取获取菜单
                router.addRoutes(res) // 动态添加可访问路由表。 (router除了可以添加路由表,也有删除路由的方法,这些东西平常你多看文档)
                next({ ...to, replace: true })// 路由添加以后进入要去的页面
              })
              .catch(() => { 
                next({ path: '/login' }) // 请求失败的话去登录页面。我这里让用户去登录页面了,因为大部分是因为token过期,但是这个做其实不太好,应该在请求响应拦截器做这件事
              })
          }
      } else {// 没登录
        if (whiteList.indexOf(to.path) !== -1) { // whiteList这个是路由的白名单,如登录页面,注册页面等不需要登录能够直接进去的
          next() // 进入页面
        } else {
          // 否则就跳到到登录页面
          next(`/login?redirect=${to.path}`)
        }
      }
    })
    动态路由的菜单渲染部分是一样的 根据hidden来判断要显示哪些菜单按钮