Vue.js
1. Register global guard Core Logic router.beforeResolve registers a global guard. Similar to router.beforeEach, except that resolve guards are called before navigation is confirmed and after all component guards and async route components are resolved. 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 When loginInterception is false, create virtual permissions await store.dispatch('User/setPermissions', ['admin']) permissions = ['admin'] } else { permissions = await store.dispatch('User/getUserInfo') } let accessRoutes = [] accessRoutes = await store.dispatch('Routes/setRoutes', permissions) // Add routes 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 global settings export default { // Whether to enable login interception loginInterception: true, // Routes that do not pass token verification routesWhiteList: ['/auth/sign-in', '/auth/register', '/401', '/404'], } 2. Vuex state management global cache routes
/** * @author Alan * @description Routing interception status management*/ 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. Routing interception/** * @author Alan * @description Determine whether the current route contains permissions* @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 Intercept routes based on the permissions array * @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. Routing menu/* * @author Alan * @description Public routing */ export const constantRoutes = [ { path: '/auth', name: 'auth1', component: AuthLayout, children: authChildRoutes('auth1'), hidden: true // hide the menu}, { 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 Asynchronous routing */ 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. Recursive menu vue component<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' : ''}`" vb-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' // Self-component 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> This is the end of this article about the sample code of vue-router dynamically generating navigation menu based on backend permissions. For more relevant vue-router permissions navigation menu content, please search 123WORDPRESS.COM's previous articles or continue to browse the following related articles. I hope everyone will support 123WORDPRESS.COM in the future! You may also be interested in:
|
<<: Analysis of Apache's common virtual host configuration methods
>>: MySQL data type optimization principles
BackUpMysql.sh script #!/bin/bash PATH=/bin:/sbin...
This article shares the specific code for JavaScr...
This article shares the specific code of JavaScri...
1. Why do we need to divide tables and partitions...
8 optimization methods for MySQL database design,...
It is very convenient to connect to a remote serv...
This article shares the specific code of js to ac...
Create a project Create a project in WeChat Devel...
Open the cpanel management backend, under the &qu...
Table of contents 1 Introduction to nginx 1 What ...
Introduction Closure is a very powerful feature i...
Copy code The code is as follows: 1. Sina Weibo &...
The data dictionary in MySQL is one of the import...
I think this is a problem that many people have en...
Note: Since .NET FrameWork cannot be run in core ...