前端项目的动态路由实现(vue)

server/2024/11/28 6:41:13/

 一、引言

动态路由,很多场景是,有些页面必须是某些用户或者某些角色才能访问,所以呢,前端的代码即使不给页面的入口,但是要是直接在地址栏敲入相关地址页面还是可以被访问到。为了杜绝这种情况,就用到了动态路由,没有权限的页面直接在路由里不注册,及时输入地址也将无效。路由信息这东西有点大,放到以上说的本地存储方式里,貌似都不合适

这个动态的配置呢主要是通过vue-router的addRoutes方法。但add的内容呢,是前端去动态配置呢,还是根据后台的接口返回呢。主要看具体使用情况,不过还是后台控制稳妥一些。这种动态的情况,实现权限控制。

一、router的beforeEach

import { get, isEmpty, replace } from 'lodash'const getCurrentUri = base => { // 获取当前地址let protocol = get(location, 'protocol')let host = get(location, 'host')let href = get(location, 'href')return replace(href, `${protocol}//${host}${base}`, '/')
}export const initRouterGuard = (router, store) => {const { dispatch, getters } = storerouter.beforeEach((to, from, next) => {console.log('\n====== In router.beforeEach ======')let {isLoggedin,menuList,activeMenu} = get(getters, 'user')// router匹配的是除设定base之外的路由,获取当前let uri = getCurrentUri(get(router, 'options.base'))console.log(`At path: ${uri}, From ${from.path} to ${to.path}`)// home为登录页,isLoggedin是一个持久化的数据,如果没有登录,访问非登录页,则跳转至登录页if (!isLoggedin && to.path !== '/home') {next('/home')// 如果登录了,但没有拿到动态路由信息,则取获取路由信息,该操作为刷新} else if (isEmpty(menuList) && isLoggedin) {console.log('Before dispatch "setMenu"')dispatch('setMenu').then(() => { // setMenu一个请求let matched = router.matcher.match(uri) // 拿到权限路由后,看当前路由是否在其中if (activeMenu && matched.name && matched.name !== 'Home') {console.log(`Current uri ${uri} get matched route`)next({ replace: true, path: uri }) // 如果有就跳转} else {matched = router.matcher.match('/dashboard')next({ replace: true, path: '/dashboard' }) // 如果没有就回到主页}matched.meta.showMenu && dispatch('switchActiveMenu', matched.name)})} else {console.log('Before default next()')to.meta.showMenu && dispatch('switchActiveMenu', to.name)next()}})
}

二、如果没有统一主页

import { get, replace, isEmpty } from 'lodash'const locationPrefix = process.env.ROUTE_BASEconst getCurrentUri = () => {let protocol = get(location, 'protocol')let host = get(location, 'host')let href = get(location, 'href')console.log('getCurrentUri', href, `${protocol}//${host}${locationPrefix}`)return replace(href, `${protocol}//${host}${locationPrefix}`, '')
}export const initRouterGuard = (router, store) => {const { dispatch, getters } = storerouter.beforeEach((to, from, next) => {console.log('to', to.path, 'from', from.path)// 首先从vuex store中获取当前用户的登录状态、菜单列表、当前激活的菜单const { isLoggedin, menuList } = get(getters, 'user')// 特殊处理,手机浏览器内核会导致isLoggedin为null而且cookie也拿不到let pendingUri = getCurrentUri()const matchedRoute = router.matcher.match(to.path)// const needRedirect = includes(pendingUri, '/detail') && !get(matchedRoute, name)console.log('matchedRoute', get(matchedRoute, name), pendingUri)// 如果用户没登录,而且即将去的页面不是登录页面,则直接重定向到登录页面if (!isLoggedin && to.name !== 'Login' && !(to.name === 'resetPwd' && to.params.type === '0')) {return next({ replace: true, name: 'Login' })}// 如果用户登录了, 但是菜单数据是空的,说明是刷新页面,需要去一下index做跳转if (isLoggedin && isEmpty(menuList) && !['Index'].includes(matchedRoute.name)) {if ((pendingUri === '/login') || (pendingUri === '/index')) {pendingUri = '/user/list'}dispatch('setPendingUri', pendingUri) // 将要去的页面存储起来return next({ replace: true, path: '/index' })}dispatch('switchActiveMenu', to.name)next()})
}

三、虚拟公共主页

<template><div>主页</div>
</template><script>
import { mapGetters, mapActions } from 'vuex'export default {name: 'Index',computed: {...mapGetters(['user','common'])},mounted () {this.loadEntries()},methods: {...mapActions(['setMenu']),async loadEntries () {try {if (this._isEmpty(this.user.menuList)) {await this.setMenu()// Redirect to pending uriconst matched = this.common.pendingUri ? this.$router.match(this.common.pendingUri) : nullconst matchedName = this._get(matched, 'name')console.log('loadEntries', this.common.pendingUri, this.$route.name, matchedName)if (this.$route.name !== matchedName && matchedName && matchedName !== 'Login') {this.$router.push(matched)}}} catch (error) {// this.$toast(error.message)}}}
}
</script>

这样就实现了一个动态路由的流转及路由的权限控制~


http://www.ppmy.cn/server/145551.html

相关文章

表的操作DDL

创建表 character set 字符集 collate 校验规则 engine 存储引擎;属性要用 ‘,’ 隔开&#xff0c;最后一个属性不加 ‘,’ &#xff0c;不要忘了括号其中charset utf8 collate utf8_general_ci engine MyIsam;可以不写 create database usr_db; use usr_db; //创建表 user1 c…

【vue3实现微信小程序】设置项目底部tab页面切换标签

快速跳转&#xff1a; 我的个人博客主页&#x1f449;&#xff1a;Reuuse博客 新开专栏&#x1f449;&#xff1a;Vue3专栏 参考文献&#x1f449;&#xff1a;uniapp官网 免费图标&#x1f449;&#xff1a;阿里巴巴矢量图标库 ❀ 感谢支持&#xff01;☀ 前情提要 &#x…

PG使用 INHERITS 创建的子表注意事项

在 PostgreSQL 中&#xff0c;使用 INHERITS 创建的子表对主表的更改行为如下&#xff1a; 1. 新增字段 行为&#xff1a;子表会自动继承主表新增的字段。 示例&#xff1a; CREATE TABLE parent_table (id SERIAL PRIMARY KEY, name TEXT); CREATE TABLE child_table () INHE…

Kubeadm 安装 Kubernetes 高可用集群 v1.30.0

1、修改主机名&#xff08;各个节点&#xff09; hostnamectl set-hostname xxx2、hosts 文件加入主机名&#xff08;全部节点&#xff09; cat /etc/hosts 192.168.88.5 master1 192.168.88.6 master2 192.168.88.7 master3 192.168.88.8 node13、关闭防火墙&#xff08;全部…

英语知识网站:Spring Boot技术构建

6系统测试 6.1概念和意义 测试的定义&#xff1a;程序测试是为了发现错误而执行程序的过程。测试(Testing)的任务与目的可以描述为&#xff1a; 目的&#xff1a;发现程序的错误&#xff1b; 任务&#xff1a;通过在计算机上执行程序&#xff0c;暴露程序中潜在的错误。 另一个…

Fastadmin系统配置增加配置字段类型

项目有一个上传APK安装包文件的需求&#xff0c;使用框架自带的 ‘文件’ 类型&#xff0c;每次都是不同路径不同文件名。希望保持固定路径和文件名所以就自己写加了一个类型&#xff0c;需要修改的地方如下&#xff1a; 1. app\common\model\Config.php 在 getTypeList 方法中…

使用R语言绘制简单地图的教程

今天主要讲的部分是绘制静态地图&#xff0c;使用的R语言绘图包是tmap&#xff0c;关于介绍就不多讲&#xff0c;下面开始代码的讲解&#xff0c;小白也可以放心食用。 1、绘制简单的单幅地图&#xff0c;这里以新西兰地区为例 #导入必要的包 library(tmap) library(sp) libr…

Android 11 三方应用监听关机广播ACTION_SHUTDOWN

前言 最近有项目过程中&#xff0c;有做app的同事反馈&#xff0c;三方应用无法监听关机广播。特地研究了下关机广播为啥监听不到。 1.原因&#xff1a;发送关机广播的类是ShutdownThread.java&#xff0c;添加了flag:Intent.FLAG_RECEIVER_FOREGROUND | Intent.FLAG_RECEIVER…