Maison >interface Web >Questions et réponses frontales >Quelles sont les deux méthodes d'implémentation du routage dynamique vue ?

Quelles sont les deux méthodes d'implémentation du routage dynamique vue ?

青灯夜游
青灯夜游original
2022-12-22 19:37:203600parcourir

Deux méthodes d'implémentation du routage dynamique vue : 1. Les paramètres de routage de rôle simples, tels que l'implication uniquement des autorisations des administrateurs et des utilisateurs ordinaires, sont généralement effectués directement sur le front-end ; 2. Paramètres d'autorisation de routage complexes, tels que le système OA et la configuration des autorisations pour plusieurs rôles ; le backend doit généralement renvoyer la liste de routage et le rendu frontal est utilisé.

Quelles sont les deux méthodes d'implémentation du routage dynamique vue ?

L'environnement d'exploitation de ce tutoriel : système windows7, version vue3, ordinateur DELL G3.

Le routage dynamique est différent du routage statique commun. Il peut modifier la liste de routage du site en fonction de différents « facteurs ».

Il existe généralement deux types de paramètres de routage dynamique :

(1) Paramètres de routage de rôle simples : par exemple, ils impliquent uniquement les autorisations des administrateurs et des utilisateurs ordinaires. Habituellement, les paramètres d'autorisation de rôle simples sont effectués directement sur le front-end

(2), les paramètres d'autorisation de routage complexes : tels que le système OA, la configuration des autorisations pour plusieurs rôles. Habituellement, le backend est requis pour renvoyer la liste de routage, et le rendu front-end est utilisé

1 Paramètres de routage de rôle simples

(1) Configurer les autorisations de routage du projet

// router.js
import Vue from 'vue'
import Router from 'vue-router'
import Layout from '@/layout'
Vue.use(Router)// 权限路由列表
let asyncRoutes = [
    {
        path: '/permission',
        component: Layout,
        redirect: '/permission/page',
        alwaysShow: true, 
        name: 'Permission',
        meta: {
            title: 'Permission',
            roles: ['admin', 'editor'] // 普通的用户角色
        },
        children: [
            {
                path: 'page',
                component: () => import('@/views/permission/page'),
                name: 'PagePermission',
                meta: {
                    title: 'Page',
                    roles: ['editor']  //  editor角色的用户才能访问该页面
                }
            },
            {
                path: 'role',
                component: () => import('@/views/permission/role'),
                name: 'RolePermission',
                meta: {
                    title: 'Role',
                    roles: ['admin']    //  admin角色的用户才能访问该页面
                }
            }
        ]
    },
 ]
 // 静态路由
 let defaultRouter = [{
    path: '/404',
    name: '404',
    component: () => import('@/views/404'),
     meta: {
        title: '404'
    }
}]
let router = new Router({
    mode: 'history',
    scrollBehavior: () => ({ y: 0 }),
    routes: defaultRouter
})
export default router

(2) Créer un nouveau public. Fichier asyncRouter.js

// asyncRouter.js
//判断当前角色是否有访问权限
function hasPermission(roles, route) {
  if (route.meta && route.meta.roles) {
    return roles.some(role => route.meta.roles.includes(role))
  } else {
    return true
  }
}

// 递归过滤异步路由表,筛选角色权限路由
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
}

(3) Créer un garde de routage : créez un fichier permission.js public et configurez un garde de routage

import router from './router'
import store from './store'
import NProgress from 'nprogress' // 进度条插件
import 'nprogress/nprogress.css' // 进度条样式
import { getToken } from '@/utils/auth' 
import { filterAsyncRoutes } from '@/utils/asyncRouter.js'
NProgress.configure({ showSpinner: false }) // 进度条配置
const whiteList = ['/login'] 
router.beforeEach(async (to, from, next) => {
    // 进度条开始
    NProgress.start()
     // 获取路由 meta 中的title,并设置给页面标题
    document.title = to.meta.title    // 获取用户登录的token
    const hasToken = getToken()
    // 判断当前用户是否登录
    if (hasToken) {
        if (to.path === '/login') {
            next({ path: '/' })
            NProgress.done()
        } else {
            // 从store中获取用户角色
            const hasRoles = store.getters.roles && store.getters.roles.length > 0  
            if (hasRoles) {
                next()
            } else {
                try {
                    // 获取用户角色
                    const roles = await store.state.roles                    // 通过用户角色,获取到角色路由表
                    const accessRoutes = filterAsyncRoutes(await store.state.routers,roles)
                    // 动态添加路由到router内
                    router.addRoutes(accessRoutes)
                    next({ ...to, replace: true })
                } catch (error) {
                    // 清除用户登录信息后,回跳到登录页去
                    next(`/login?redirect=${to.path}`)
                    NProgress.done()
                }
            }
        }
    } else {
        // 用户未登录
        if (whiteList.indexOf(to.path) !== -1) {
            // 需要跳转的路由是否是whiteList中的路由,若是,则直接条状
            next()
        } else {
            // 需要跳转的路由不是whiteList中的路由,直接跳转到登录页
            next(`/login?redirect=${to.path}`)
            // 结束精度条
            NProgress.done()
        }
    }})
    router.afterEach(() => {
    // 结束精度条
    NProgress.done()
   })

(4) Introduisez le fichier permission.js dans main.js

(5) Store rôles dans le magasin lors de la connexion

2. Paramètres d'autorisation de routage complexes (le backend renvoie dynamiquement les données de routage)

(1) Configurez le fichier de routage du projet Il n'y a pas de routes dans le fichier, ou il y en a. routes publiques, c'est-à-dire des routes sans autorisations

import Vue from 'vue'
import Router from 'vue-router'
import Layout from '@/layout';
Vue.use(Router)// 配置项目中没有涉及权限的公共路由
export const constantRoutes = [
    {
        path: '/login',
        component: () => import('@/views/login'),
        hidden: true
    },
    {
        path: '/404',
        component: () => import('@/views/404'),
        hidden: true
    },
]
const createRouter = () => new Router({
    mode: 'history',
    scrollBehavior: () => ({ y: 0 }),
    routes: constantRoutes
})
const router = createRouter()
export function resetRouter() {
    const newRouter = createRouter()
    router.matcher = newRouter.matcher
}
export default router

(2) Créez un nouveau fichier public asyncRouter.js

// 引入路由文件这种的公共路由
import { constantRoutes } from '../router';// Layout 组件是项目中的主页面,切换路由时,仅切换Layout中的组件
import Layout from '@/layout';
export function getAsyncRoutes(routes) {
    const res = []
    // 定义路由中需要的自定名
    const keys = ['path', 'name', 'children', 'redirect', 'meta', 'hidden']
    // 遍历路由数组去重组可用的路由
    routes.forEach(item => {
        const newItem = {};
        if (item.component) {
            // 判断 item.component 是否等于 'Layout',若是则直接替换成引入的 Layout 组件
            if (item.component === 'Layout') {
                newItem.component = Layout
            } else {
            //  item.component 不等于 'Layout',则说明它是组件路径地址,因此直接替换成路由引入的方法
                newItem.component = resolve => require([`@/views/${item.component}`],resolve)
                
                // 此处用reqiure比较好,import引入变量会有各种莫名的错误
                // newItem.component = (() => import(`@/views/${item.component}`));
            }
        }
        for (const key in item) {
            if (keys.includes(key)) {
                newItem[key] = item[key]
            }
        }
        // 若遍历的当前路由存在子路由,需要对子路由进行递归遍历
        if (newItem.children && newItem.children.length) {
            newItem.children = getAsyncRoutes(item.children)
        }
        res.push(newItem)
    })
    // 返回处理好且可用的路由数组
    return res
 }

(3) Créez un garde de routage : créez un fichier permission.js public et configurez un garde de routage

//  进度条引入设置如上面第一种描述一样
import router from './router'
import store from './store'
import NProgress from 'nprogress' // progress bar
import 'nprogress/nprogress.css' // progress bar style
import { getToken } from '@/utils/auth' // get token from cookie
import { getAsyncRoutes } from '@/utils/asyncRouter'
const whiteList = ['/login'];
router.beforeEach( async (to, from, next) => {
    NProgress.start()
    document.title = to.meta.title;
    // 获取用户token,用来判断当前用户是否登录
    const hasToken = getToken()
    if (hasToken) {
        if (to.path === '/login') {
            next({ path: '/' })
            NProgress.done()
        } else {
            //异步获取store中的路由
            let route = await store.state.addRoutes;
            const hasRouters = route && route.length>0;
            //判断store中是否有路由,若有,进行下一步
            if ( hasRouters ) {
                next()
            } else {
                //store中没有路由,则需要获取获取异步路由,并进行格式化处理
                try {
                    const accessRoutes = getAsyncRoutes(await store.state.addRoutes );
                    // 动态添加格式化过的路由
                    router.addRoutes(accessRoutes);
                    next({ ...to, replace: true })
                } catch (error) {
                    // Message.error('出错了')
                    next(`/login?redirect=${to.path}`)
                    NProgress.done()
                }
            }
        }
    } else {
        if (whiteList.indexOf(to.path) !== -1) {
            next()
        } else {
            next(`/login?redirect=${to.path}`)
            NProgress.done()
        }
    }})router.afterEach(() => {
    NProgress.done()
 })

(4) Introduisez le fichier permission.js dans main.js

(5) Stockez les informations de routage dans le magasin lors de la connexion

//  登录接口调用后,调用路由接口,后端返回相应用户的路由res.router,我们需要存储到store中,方便其他地方拿取
this.$store.dispatch("addRoutes", res.router);

À ce stade, l'intégralité de l'itinéraire dynamique peut être utilisée, mais le saut de page et le garde d'itinéraire le traitement est asynchrone et il y aura un saut après l'ajout de la route dynamique. La page est redirigée vers une page vierge. En effet, les données dans le routeur n'existent pas encore lorsque la route s'exécute next(). vous pouvez actualiser l'itinéraire via window.location.reload()
Le format d'itinéraire renvoyé par le backend :

routerList = [
  {
        "path": "/other",
        "component": "Layout",
        "redirect": "noRedirect",
        "name": "otherPage",
        "meta": {
            "title": "测试",
        },
        "children": [
            {
                "path": "a",
                "component": "file/a",
                "name": "a",
                "meta": { "title": "a页面", "noCache": "true" }
            },
            {
                "path": "b",
                "component": "file/b",
                "name": "b",
                "meta": { "title": "b页面", "noCache": "true" }
            },
        ]
    }
]

Remarque : Vue est une application d'une seule page, donc une partie des données sera perdue dès que la page est actualisée , nous devons donc stocker les données dans le magasin localement pour garantir que le routage ne soit pas perdu.

【Recommandations associées : tutoriel vidéo vuejs, développement web front-end

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn