Mainstream implementation methods: Let's briefly talk about the advantages of the two methods. After all, if you have never done it, no matter how much you say, you still can't understand it. You still have to look at the code. Front-end control
Backend control
1. Front-end control Idea: In the routing configuration, through the Specific plan:
Core code logic 1. In the router.js file (write static routing and dynamic routing in router.js respectively)import Vue from 'vue' import Router from 'vue-router' Vue.use(Router) import Layout from '@/layout' // constantRoutes static routing, mainly login page, 404 page, etc. do not require dynamic routing export const constantRoutes = [ { path: '/redirect', component: Layout, hidden: true, children: [ { path: '/redirect/:path*', component: () => import('@/views/redirect/index') } ] }, { path: '/login', component: () => import('@/views/login/index'), hidden: true }, { path: '/404', component: () => import('@/views/error-page/404'), hidden: true }, { path: '/401', component: () => import('@/views/error-page/401'), hidden: true } ] // asyncRoutes dynamic routing export const asyncRoutes = [ { path: '/permission', component: Layout, redirect: '/permission/page', alwaysShow: true, name: 'Permission', meta: { title: 'Permission', icon: 'lock', // The core code can be traversed by the assigned roles to determine whether to display // This means the two roles of admin and editor. This menu can display roles: ['admin', 'editor'] }, children: [ { path: 'page', component: () => import('@/views/permission/page'), name: 'PagePermission', meta: { title: 'Page Permission', // This means that only admin can display roles: ['admin'] } } ] } ] const createRouter = () => new Router({ scrollBehavior: () => ({ y: 0 }), routes: constantRoutes }) const router = createRouter() // This is used to reset the router, very useful, don't look at these few lines of code export function resetRouter() { const newRouter = createRouter() router.matcher = newRouter.matcher } export default router 2. store/permission.js (maintain a state in vuex and control whether the menu is displayed by assigning roles)import { asyncRoutes, constantRoutes } from '@/router' // This method is used to match roles with route.meta.role function hasPermission(roles, route) { if (route.meta && route.meta.roles) { return roles.some(role => route.meta.roles.includes(role)) } else { return true } } // This method uses recursion to traverse the routes and traverse the routes with permissions export function filterAsyncRoutes(routes, roles) { const res = [] routes.forEach(route => { const tmp = { ...route } if (hasPermission(roles, tmp)) { if (tmp.children) { tmp.children = filterAsyncRoutes(tmp.children, roles) } res.push(tmp) } }) return res } const state = { routes: [], addRoutes: [] } const mutations = { SET_ROUTES: (state, routes) => { // This place maintains two states, one is addRouters and the other is routes state.addRoutes = routes state.routes = constantRoutes.concat(routes) } } const actions = { generateRoutes({ commit }, roles) { return new Promise(resolve => { let accessedRoutes if (roles.includes('admin')) { accessedRoutes = asyncRoutes || [] } else { // Core code, pass the route and the obtained role (obtained in the background) in for matching accessedRoutes = filterAsyncRoutes(asyncRoutes, roles) } // Set the matched and authorized routes to vuex commit('SET_ROUTES', accessedRoutes) resolve(accessedRoutes) }) } } export default { namespaced: true, state, mutations, actions } 3. src/permission.js(Create a new routing guard function, which can be in main.js or extracted into a file) The code here is mainly to control the route jump before checking which routes are accessible. The logic of jumping after logging in can be written here. // permission.js router.beforeEach((to, from, next) => { if (store.getters.token) { // Check if there is a token if (to.path === '/login') { next({ path: '/' }); } else { // Determine whether the current user has retrieved all user_info information if (store.getters.roles.length === 0) { store.dispatch('GetInfo').then(res => { // Pull info const roles = res.data.role; // Pass the obtained role in for matching and generate accessible routes store.dispatch('GenerateRoutes', { roles }).then(() => { // Dynamically add accessible routing tables (core code, nothing can be done without it) router.addRoutes(store.getters.addRouters) // hack to ensure addRoutes is complete next({ ...to, replace: true }) }) }).catch(err => { console.log(err); }); } else { next() //When there is user permission, it means that all accessible routes have been generated. If you do not have permission to access, you will automatically enter the 404 page.} } } else { if (whiteList.indexOf(to.path) !== -1) { // In the login-free whitelist, go directly to next(); } else { next('/login'); // Otherwise redirect all to the login page} } }) 4. The sidebar can fetch data from vuex for rendering The core code is to get the available routing object from <!-- layout/components/siderbar.vue --> <el-menu :default-active="activeMenu" :collapse="isCollapse" :background-color="variables.menuBg" :text-color="variables.menuText" :unique-opened="false" :active-text-color="variables.menuActiveText" :collapse-transition="false" mode="vertical" > // Loop through the routes and pass them to the child component as parameters <sidebar-item v-for="route in routes" :key="route.path" :item="route" :base-path="route.path" /> </el-menu> // Get authorized routes routes() { return this.$router.options.routes } <!-- layout/components/siderbarItem.vue --> <template slot="title"> <item v-if="item.meta" :icon="item.meta && item.meta.icon" :title="item.meta.title" /> </template> <sidebar-item v-for="child in item.children" :key="child.path" :is-nest="true" :item="child" :base-path="resolvePath(child.path)" class="nest-menu" /> props: { // route object item: type: Object, required: true }, isNest: { type: Boolean, default: false }, basePath: { type: String, default: '' } } The front-end controls the routing, and the logic is relatively simple. The back-end only needs to store the user's role, and the front-end uses the user's role for matching. But if you add new characters, it will be very painful because you have to add every one of them. 2. Backend Control RoutingThe general idea of backend control is: the routing configuration is placed in the database table. After the user logs in successfully, the menu with permissions is passed to the frontend according to the role permissions. The frontend formats it into a structure recognized by the page routing and then renders it to the page menu.
Specific logic:
Because the processes behind the front-end control and the back-end control are mostly the same, we will only look at the different processes at the front: 1. store/permission.js, send a request to get data in vuexGenerateRoutes({ commit }, data) { return new Promise((resolve, reject) => { getRoute(data).then(res => { //Convert the acquired data and save it in vuex const accessedRouters = arrayToMenu(res.data) accessedRouters.concat([{ path: '*', redirect: '/404', hidden: true }]) commit('SET_ROUTERS', accessedRouters) resolve() }).catch(error => { reject(error) }) }) } 2. Organize a data structure and save it in the table// Page routing format { path: '/form', component: Layout, children: [ { path: 'index', name: 'Form', component: () => import('@/views/form/index'), meta: { title: 'Form', icon: 'form' } } ] } // Data format after sorting // First level menu // ParentId 0 can be used as a first level menu. It is best to choose a 4-digit ID. You will know why when you develop the project. id: 1300 parentId: 0 title: "Menu Management" path: "/menu" hidden: false component: null hidden: false name: "menu" }, // Secondary menu // If parentId is not 0, you can match parentId with the id of the primary menu, and push the matching one into children { id: 1307 parentId: 1300 title: "Submenu" hidden: false path: "menuItem" component: "menu/menuItem" // To match the local file address hidden: false name: "menuItem" } 3. Write a conversion method to convert the acquired data into a router structureexport function arrayToMenu(array) { const nodes = [] // Get the top node for (let i = 0; i < array.length; i++) { const row = array[i] // This exists method is to determine whether there is a child if (!exists(array, row.parentId)) { nodes.push({ path: row.path, // route address hidden: row.hidden, // all true, if the backend is not configured component: Layout, // generally matches the component of your file name: row.name, // route name meta: { title: row.title, icon: row.name }, // title is the displayed name id: row.id, // route id redirect: 'noredirect' }) } } const toDo = Array.from(nodes) while (toDo.length) { const node = toDo.shift() // Get child nodes for (let i = 0; i < array.length; i++) { const row = array[i] // push to the parent whose parentId is equal to if (row.parentId === node.id) { const child = { path: row.path, name: row.name, hidden: row.hidden, // Core code, because the component of the secondary route needs to match the component of the page: require('@/views/' + row.component + '/index.vue'), meta: { title: row.title, icon: row.name }, id: row.id } if (node.children) { node.children.push(child) } else { node.children = [child] } toDo.push(child) } } } return nodes } // Check if there are any children function exists(rows, parentId) { for (let i = 0; i < rows.length; i++) { if (rows[i].id === parentId) return true } return false } This is the end of this detailed article about Vue's implementation of dynamic routing. For more relevant Vue's implementation of dynamic routing 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:
|
<<: Instructions for using the --rm option of docker run
>>: Analysis of Sysbench's benchmarking process for MySQL
Use runlike to view the docker run startup parame...
Preface In web applications, in order to save tra...
Before, I had built WordPress myself, but at that...
my.cnf is the configuration file loaded when MySQ...
Attribute check-strictly The official document pr...
This article shares the specific code of JQuery t...
Since my local MySQL version is relatively low, I...
1. Introduction When the amount of data in the da...
1. Preparation Example: Two machines: 192.168.219...
1. Monitoring planning Before creating a monitori...
Ubuntu is a free and open source desktop PC opera...
Table of contents Purpose Experimental environmen...
Table of contents Experimental environment Instal...
As shown in the following figure: When we use vir...
Preface At work, I need to count the materials su...