您当前的位置:首页 > 网站建设 > javascript
| php | asp | css | H5 | javascript | Mysql | Dreamweaver | Delphi | 网站维护 | 帝国cms | React | 考试系统 | ajax | jQuery | 小程序 |

vue-router 基于后端permissions动态生成导航菜单的示例代码

51自学网 2022-02-21 13:40:31
  javascript

Vue.js

1、注册全局守卫

核心逻辑
1、token身份验证(后端) => token失效返回登录页面
2、获取用户权限
3、校验permissions,动态添加路由菜单

router.beforeResolve 注册一个全局守卫。和 router.beforeEach 类似,区别是在导航被确认之前,同时在所有组件内守卫和异步路由组件被解析之后,解析守卫就被调用。

router.beforeResolve(async (to, from, next) => {  let hasToken = store.getters['User/accessToken']  if (!settings.loginInterception) hasToken = true  if (hasToken) {    if (to.path === '/auth/sign-in') {      next({ path: '/' })    } else {      const hasPermissions =        store.getters['User/permissions'] &&        store.getters['User/permissions'].length > 0      if (hasPermissions) {        next()      } else {        try {          let permissions          if (!constant.loginInterception) {            // settings.js loginInterception为false时,创建虚拟权限            await store.dispatch('User/setPermissions', ['admin'])            permissions = ['admin']          } else {            permissions = await store.dispatch('User/getUserInfo')          }          let accessRoutes = []          accessRoutes = await store.dispatch('Routes/setRoutes', permissions)          // 添加路由          router.addRoutes(accessRoutes)          next({ ...to, replace: true })        } catch {          await store.dispatch('User/resetAccessToken')        }      }    }  } else {    if (settings.routesWhiteList.indexOf(to.path) !== -1) {      next()    } else {      next('/auth/sign-in')    }  }  document.title = getPageTitle(to.meta.title)})

settings.js 全局设置

export default {  // 是否开启登录拦截  loginInterception: true,  // 不经过token校验的路由  routesWhiteList: ['/auth/sign-in', '/auth/register', '/401', '/404'],}

2、Vuex状态管理 全局缓存routes

  • state :对数据的全局存储
  • getter: 可以理解为computed ,对数据进行计算
  • mutations :对数据的同步更改
  • actions:对数据的异步更改(实现异步操作)
  • module: 将 store 分割成模块
/** * @author Alan * @description 路由拦截状态管理 */import { asyncRoutes, constantRoutes } from '@/router'import { filterAsyncRoutes } from '@/Utils/handleRoutes'const state = () => ({  routes: [],  partialRoutes: []})const getters = {  routes: (state) => state.routes,  partialRoutes: (state) => state.partialRoutes}const mutations = {  setRoutes (state, routes) {    state.routes = constantRoutes.concat(routes)  },  setPartialRoutes (state, routes) {    state.partialRoutes = constantRoutes.concat(routes)  }}const actions = {  async setRoutes ({ commit }, permissions) {    const finallyAsyncRoutes = await filterAsyncRoutes(      [...asyncRoutes],      permissions    )    commit('setRoutes', finallyAsyncRoutes)    return finallyAsyncRoutes  },  setPartialRoutes ({ commit }, accessRoutes) {    commit('setPartialRoutes', accessRoutes)    return accessRoutes  }}export default { namespaced: true, state, getters, mutations, actions }

3、路由拦截

/** * @author Alan * @description 判断当前路由是否包含权限 * @param permissions * @param route * @returns {boolean|*} */export function hasPermission (permissions, route) {  if (route.meta && route.meta.permissions) {    return permissions.some((role) => route.meta.permissions.includes(role))  } else {    return true  }}/** * @author Alan * @description 根据permissions数组拦截路由 * @param routes * @param permissions * @returns {[]} */export function filterAsyncRoutes (routes, permissions) {  const finallyRoutes = []  routes.forEach((route) => {    const item = { ...route }    if (hasPermission(permissions, item)) {      if (item.children) {        item.children = filterAsyncRoutes(item.children, permissions)      }      finallyRoutes.push(item)    }  })  return finallyRoutes}

4、路由菜单

/** @author Alan* @description 公共路由*/export const constantRoutes = [  {    path: '/auth',    name: 'auth1',    component: AuthLayout,    children: authChildRoutes('auth1'),    hidden: true // 隐藏菜单  },  {    path: '/',    name: 'dashboard',    component: VerticleLayout,    meta: {      title: 'Dashboard',      name: 'sidebar.dashboard',      is_heading: false,      is_active: false,      link: '',      class_name: '',      is_icon_class: true,      icon: 'ri-home-4-line',      permissions: ['admin']    },    children: childRoutes('dashboard')  }]/** @author Alan* @description 异步路由*/export const asyncRoutes = [  {    path: '/menu-design',    name: 'horizontal-dashboard',    component: HorizantalLayout,    meta: {      title: 'Menu Design',      name: 'sidebar.MenuDesign',      is_heading: false,      is_active: false,      link: '',      class_name: '',      is_icon_class: true,      icon: 'ri-menu-3-line',      permissions: ['admin']    },    children: horizontalRoute('dashboard')  }, {    path: '/core',    name: 'core',    component: VerticleLayout,    meta: {      title: 'UI Elements',      name: 'sidebar.uiElements',      is_heading: false,      is_active: false,      class_name: '',      link: '',      is_icon_class: true,      icon: 'ri-pencil-ruler-line',      permissions: ['admin']    },    children: coreChildRoute('core')  }]

5、递归菜单vue组件

<template>  <b-collapse tag="ul" :class="className" :visible="open" :id="idName" :accordion="accordianName">    <li v-for="(item,index) in items" :key="index" :class=" !hideListMenuTitle? 'p-0' : item.meta.is_heading ? 'iq-menu-title' :activeLink(item) && item.children ? 'active' : activeLink(item) ? 'active' : ''">      <template v-if="!item.hidden">        <i v-if="item.meta.is_heading && hideListMenuTitle" class="ri-subtract-line" />        <span v-if="item.meta.is_heading && hideListMenuTitle">{{ $t(item.meta.name) }}</span>        <router-link :to="item.meta.link" v-if="!item.is_heading" :class="`iq-waves-effect ${activeLink(item) && item.children ? 'active' : activeLink(item) ? 'active' : ''}`" v-b-toggle="item.meta.name">          <i :class="item.meta.icon" v-if="item.meta.is_icon_class"/>          <template v-else v-html="item.meta.icon">          </template>          <span>{{ $t(item.meta.name) }}</span>          <i v-if="item.children" class="ri-arrow-right-s-line iq-arrow-right" />          <small v-html="item.meta.append" v-if="hideListMenuTitle" :class="item.meta.append_class" />        </router-link>        <List v-if="item.children" :items="item.children" :sidebarGroupTitle="hideListMenuTitle" :open="item.meta.link.name !== '' && activeLink(item) && item.children ? true : !!(item.meta.link.name !== '' && activeLink(item))" :idName="item.meta.name" :accordianName="`sidebar-accordion-${item.meta.class_name}`" :className="`iq-submenu ${item.meta.class_name}`" />      </template>    </li>  </b-collapse></template><script>import List from './CollapseMenu' // 自身组件import { core } from '../../../config/pluginInit'export default {  name: 'List',  props: {    items: Array,    className: { type: String, default: 'iq-menu' },    open: { type: Boolean, default: false },    idName: { type: String, default: 'sidebar' },    accordianName: { type: String, default: 'sidebar' },    sidebarGroupTitle: { type: Boolean, default: true }  },  components: {    List  },  computed: {    hideListMenuTitle () {      return this.sidebarGroupTitle    }  },  mounted () {  },  methods: {    activeLink (item) {      return core.getActiveLink(item, this.$route.name)    }  }}</script>

到此这篇关于vue-router 基于后端permissions动态生成导航菜单的示例代码的文章就介绍到这了,更多相关vue-router permissions导航菜单内容请搜索51zixue.net以前的文章或继续浏览下面的相关文章希望大家以后多多支持51zixue.net! 


下载地址:
JavaScript实现换肤效果(换背景)
JavaScript实现表格动态变色
万事OK自学网:51自学网_软件自学网_CAD自学网自学excel、自学PS、自学CAD、自学C语言、自学css3实例,是一个通过网络自主学习工作技能的自学平台,网友喜欢的软件自学网站。