Vue 动态权限路由实现菜单列表之进阶版

需求:根据登录用户的权限,显示不同导航菜单也,同时操作不同的界面。

(1)首先在本地配置好固定不变的路由地址,例如登录,首页这些页面,如下:

import Vue from 'vue'
import Router from 'vue-router'
import LoginView from '@/views/login/Common'

Vue.use(Router)

let constRouter = [
  { path: '/login', name: '登录页', component: LoginView },
  { path: '/index', name: '首页', redirect: '/home' }
]

let router = new Router({
  routes: constRouter
})

export default router

(2)全局前置守卫:router.beforeEach,渲染动态路由。

当一个导航触发时,全局前置守卫按照创建顺序调用。守卫是异步解析执行,此时导航在所有守卫 resolve 完之前一直处于 等待中

每个守卫方法接收三个参数:

  • to: Route: 即将要进入的目标 路由对象

  • from: Route: 当前导航正要离开的路由

  • next: Function: 一定要调用该方法来 resolve 这个钩子。执行效果依赖 next 方法的调用参数。

const whiteList = ['/login']
let asyncRouter

router.beforeEach((to, from, next) => {
  if (whiteList.indexOf(to.path) !== -1) {
    next()
  }
  let token = db.get('USER_TOKEN')
  let user = db.get('USER')
  let userRouter = get('USER_ROUTER')  // 获取本地缓存
  if (token.length && user) {
    if (!asyncRouter) {
      if (!userRouter) {
        // 请求用户菜单列表接口
      } else {
        asyncRouter = userRouter
      }
    } else {
      next()
    }
  } else {
    next('/login')
  }
})

主要逻辑分为下面几步:

  1. 判断要跳转的路由地址是否在路由白名单内,是的话放行,不是的话进行第2步;

  2. 从内存中获取token和用户信息,如果存在则进行第3步,不存在跳转到登录页;

  3. 判断动态路由信息是否存在,存在则放行,不存在则进行第4步;

  4. 判断用户路由是否已经加载,是的话将用户路由赋值给动态路由,并执行路由添加操作,然后跳转;如果用户路由不存在,则执行第5步;

  5. 根据用户名从后台获取用户路由信息,并将其保存到内存中,再执行路由添加操作,然后跳转

(3)通过接口返回的权限菜单列表信息;

request.get(`menu/${user.username}`).then((res) => {
  asyncRouter = res.data
  save('USER_ROUTER', asyncRouter)  // 本地缓存
  go(to, next)
})

接口返回的路由信息:

(4)拿到权限路由信息后,需要我们在本地对数据进行处理,注册动态路由:router.addRoutes 是动态添加更多的路由规则。参数必须是一个符合 routes 选项要求的数组。

function go (to, next) {
  asyncRouter = filterAsyncRouter(asyncRouter)
  router.addRoutes(asyncRouter)
  next({...to, replace: true})
}

(5)通过 filterAsyncRouter 方法,将传入的路由数组中 component 属性做处理之后,返回数组。

import Vue from 'vue'
import Router from 'vue-router'
import MenuView from '@/views/common/MenuView'
import PageView from '@/views/common/PageView'
import EmptyPageView from '@/views/common/EmptyPageView'
import HomePageView from '@/views/HomePage'

function filterAsyncRouter (routes) {
  return routes.filter((route) => {
    let component = route.component
    if (component) {
      switch (route.component) {
        case 'MenuView': route.component = MenuView  break
        case 'PageView': route.component = PageView  break
        case 'EmptyPageView': route.component = EmptyPageView break
        case 'HomePageView': route.component = HomePageView  break
        default: route.component = view(component)
      }
      if (route.children && route.children.length) {
        route.children = filterAsyncRouter(route.children)
      }
      return true
    }
  })
}

(6)根据路由,导入对应真实的文件信息:

function view (path) {
  return function (resolve) {
    import(`@/views/${path}.vue`).then(mod => {
      resolve(mod)
    })
  }
}

(7)如何正确显示左边菜单栏信息呢?

// 底层组件
render (h) {
  return h(
    Menu,
    {
      props: {
        theme: this.$props.theme,
        mode: this.$props.mode,
        openKeys: this.openKeys,
        selectedKeys: this.selectedKeys
      },
      on: {
        openChange: this.onOpenChange,
        select: (obj) => {
          this.selectedKeys = obj.selectedKeys
          this.$emit('select', obj)
        }
      }
    }, this.renderMenu(h, this.menuData)
  )
}

(8)父组件调用菜单组件:

// GlobalLayout.vue
<sider-menu :theme="theme" :menuData="menuData" :collapsed="false" :collapsible="false" @menuSelect="onMenuSelect"/>

let menuData = []
beforeCreate () {
  let routers = this.$db.get('USER_ROUTER')
  menuData = routers.find((item) => item.path === '/').children.filter((menu) => {
    let meta = menu.meta
    if (typeof meta.isShow === 'undefined') {
      return true
    } else return meta.isShow
  })
}
// SiderMenu.vue
<i-menu :theme="theme" :collapsed="collapsed" :menuData="menuData" @select="onSelect"/>
wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==uploading.4e448015.gif转存失败重新上传取消 wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Vue 3中实现动态路由导航菜单的方法如下: 1. 首先,在Vue项目中安装Vue Router,可以使用以下命令进行安装: ``` npm install vue-router@next ``` 2. 在项目的入口文件(通常是main.js)中引入Vue Router,并创建一个路由实例: ```javascript import { createApp } from 'vue' import { createRouter, createWebHistory } from 'vue-router' import App from './App.vue' const router = createRouter({ history: createWebHistory(), routes: [ // 定义路由配置 ] }) const app = createApp(App) app.use(router) app.mount('#app') ``` 3. 在路由配置中定义动态路由和对应的组件。可以使用`component`属性指定组件,使用`path`属性指定路由路径,使用`name`属性指定路由名称,使用`meta`属性传递额外的信息等。例如: ```javascript const routes = [ { path: '/', name: 'Home', component: Home }, { path: '/about', name: 'About', component: About }, // 其他动态路由配置 ] ``` 4. 在Vue组件中使用`router-link`组件来生成导航链接,使用`router-view`组件来显示对应的组件内容。例如,在导航菜单组件中可以这样使用: ```html <template> <div> <router-link to="/">Home</router-link> <router-link to="/about">About</router-link> <!-- 其他导航链接 --> <router-view></router-view> </div> </template> ``` 5. 在Vue组件中可以通过`$router`对象进行路由导航,例如: ```javascript methods: { goToAbout() { this.$router.push('/about') } } ``` 6. 最后,根据需要可以使用路由守卫(如`beforeEach`、`beforeResolve`、`afterEach`等)来进行路由权限控制、页面加载前的处理等。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值