Vue 增加动态路由功能 【在原有系统上增加】
目录
遇到问题
1. 修改router/index.js
2. 修改 store文件夹下的
2.1 增加 modules/permission.js
2.2 增加modules/tagsViews.js
2.3 修改modules/user.js
2.4 修改getter.js
2.5 修改index.js
遇到问题
1.当出现循环刷新页面,不断进行请求时,检查配置的动态菜单 权限是否配置正确;切换身份导致菜单不发生变化;
2. Duplicate named routes definition [菜单配置不对]
由于我的配置的菜单下 只有一个菜单,我是将【1】 里的 roles配置 加到 【2】 上导致 登陆时封装菜单错误,不断刷新页面,登陆成功后切换身份也导致菜单显示不对。
3.问题描述 配置好动态路由后,在动态路由的路径刷新页面报 ,第一次点击是好的,一旦刷新页面出以下问题
Error in beforeCreate hook: "RangeError: Maximum call stack size exceeded"
RangeError: Maximum call stack size exceeded
Error in render: "TypeError: Cannot read properties of undefined (reading 'matched')"
Vue-router-3.0.1 使用router.addRoutes()设置动态路由,页面刷新后无效 - #25 by BruceChoo7 - 中文 - Vue Forumhttps://forum.vuejs.org/t/vue-router-3-0-1-router-addroutes/33181/25
解决办法
初始路由不要加重定向到404路由,否则beforeEach时地址已经变成/404了,将 404 添加到动态地址中
1. 修改router/index.js
增加
export const asyncRoutes = [{path: '/qw',component: Layout,name: 'qw',meta: { title: '企微微信', icon: 'el-icon-files',roles: ['admin', 'dev'] },children: [{path: 'msg',name: 'msg',component: () => import('@/views/qw/msg'),meta: { title: '企微消息素材管理', icon: 'el-icon-document'}}]}
]
2. 修改 store文件夹下的
2.1 增加 modules/permission.js
import { asyncRoutes, constantRoutes } from '@/router'/*** Use meta.role to determine if the current user has permission* @param roles* @param route*/
function hasPermission(roles, route) {if (route.meta && route.meta.roles) {return roles.some(role => route.meta.roles.includes(role))} else {return true}
}/*** Filter asynchronous routing tables by recursion* @param routes asyncRoutes* @param roles*/
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) => {state.addRoutes = routesstate.routes = constantRoutes.concat(routes)}
}const actions = {generateRoutes({ commit }, roles) {return new Promise(resolve => {let accessedRoutesif (roles.includes('admin')) {accessedRoutes = asyncRoutes || []} else {accessedRoutes = filterAsyncRoutes(asyncRoutes, roles)}commit('SET_ROUTES', accessedRoutes)resolve(accessedRoutes)})}
}export default {namespaced: true,state,mutations,actions
}
2.2 增加modules/tagsViews.js
const state = {visitedViews: [],cachedViews: []
}const mutations = {ADD_VISITED_VIEW: (state, view) => {if (state.visitedViews.some(v => v.path === view.path)) returnstate.visitedViews.push(Object.assign({}, view, {title: view.meta.title || 'no-name'}))},ADD_CACHED_VIEW: (state, view) => {if (state.cachedViews.includes(view.name)) returnif (!view.meta.noCache) {state.cachedViews.push(view.name)}},DEL_VISITED_VIEW: (state, view) => {for (const [i, v] of state.visitedViews.entries()) {if (v.path === view.path) {state.visitedViews.splice(i, 1)break}}},DEL_CACHED_VIEW: (state, view) => {const index = state.cachedViews.indexOf(view.name)index > -1 && state.cachedViews.splice(index, 1)},DEL_OTHERS_VISITED_VIEWS: (state, view) => {state.visitedViews = state.visitedViews.filter(v => {return v.meta.affix || v.path === view.path})},DEL_OTHERS_CACHED_VIEWS: (state, view) => {const index = state.cachedViews.indexOf(view.name)if (index > -1) {state.cachedViews = state.cachedViews.slice(index, index + 1)} else {// if index = -1, there is no cached tagsstate.cachedViews = []}},DEL_ALL_VISITED_VIEWS: state => {// keep affix tagsconst affixTags = state.visitedViews.filter(tag => tag.meta.affix)state.visitedViews = affixTags},DEL_ALL_CACHED_VIEWS: state => {state.cachedViews = []},UPDATE_VISITED_VIEW: (state, view) => {for (let v of state.visitedViews) {if (v.path === view.path) {v = Object.assign(v, view)break}}}
}const actions = {addView({ dispatch }, view) {dispatch('addVisitedView', view)dispatch('addCachedView', view)},addVisitedView({ commit }, view) {commit('ADD_VISITED_VIEW', view)},addCachedView({ commit }, view) {commit('ADD_CACHED_VIEW', view)},delView({ dispatch, state }, view) {return new Promise(resolve => {dispatch('delVisitedView', view)dispatch('delCachedView', view)resolve({visitedViews: [...state.visitedViews],cachedViews: [...state.cachedViews]})})},delVisitedView({ commit, state }, view) {return new Promise(resolve => {commit('DEL_VISITED_VIEW', view)resolve([...state.visitedViews])})},delCachedView({ commit, state }, view) {return new Promise(resolve => {commit('DEL_CACHED_VIEW', view)resolve([...state.cachedViews])})},delOthersViews({ dispatch, state }, view) {return new Promise(resolve => {dispatch('delOthersVisitedViews', view)dispatch('delOthersCachedViews', view)resolve({visitedViews: [...state.visitedViews],cachedViews: [...state.cachedViews]})})},delOthersVisitedViews({ commit, state }, view) {return new Promise(resolve => {commit('DEL_OTHERS_VISITED_VIEWS', view)resolve([...state.visitedViews])})},delOthersCachedViews({ commit, state }, view) {return new Promise(resolve => {commit('DEL_OTHERS_CACHED_VIEWS', view)resolve([...state.cachedViews])})},delAllViews({ dispatch, state }, view) {return new Promise(resolve => {dispatch('delAllVisitedViews', view)dispatch('delAllCachedViews', view)resolve({visitedViews: [...state.visitedViews],cachedViews: [...state.cachedViews]})})},delAllVisitedViews({ commit, state }) {return new Promise(resolve => {commit('DEL_ALL_VISITED_VIEWS')resolve([...state.visitedViews])})},delAllCachedViews({ commit, state }) {return new Promise(resolve => {commit('DEL_ALL_CACHED_VIEWS')resolve([...state.cachedViews])})},updateVisitedView({ commit }, view) {commit('UPDATE_VISITED_VIEW', view)}
}export default {namespaced: true,state,mutations,actions
}
2.3 修改modules/user.js
import { login, logout, getInfo } from '@/api/user'
import { getToken, setToken, removeToken } from '@/utils/auth'
import router,{ resetRouter } from '@/router'const getDefaultState = () => {return {token: getToken(),name: '',group:'',roles:'',avatar: ''}
}const state = getDefaultState()const mutations = {RESET_STATE: (state) => {Object.assign(state, getDefaultState())},SET_TOKEN: (state, token) => {state.token = token},SET_NAME: (state, name) => {state.name = name},SET_GROUP: (state, group) => {state.group = group},SET_ROLES: (state, roles) => {state.roles = roles},SET_AVATAR: (state, avatar) => {state.avatar = avatar}
}const actions = {// user loginlogin({ commit }, userInfo) {const { username, password } = userInforeturn new Promise((resolve, reject) => {login({ username: username.trim(), password: password }).then(response => {const { data } = responsecommit('SET_TOKEN', data.token)// commit('SET_NAME', data.username)// commit('SET_GROUP', data.group)// commit('SET_ROLES', data.role)setToken(data.token)resolve()}).catch(error => {reject(error)})})},// get user infogetInfo({ commit, state }) {return new Promise((resolve, reject) => {getInfo(state.token).then(response => {console.log(response)const { data } = responseif (!data) {reject('Verification failed, please Login again.')}console.log(data)const { username, avatar,group,roles } = datacommit('SET_NAME', username)commit('SET_AVATAR', avatar)commit('SET_GROUP', group)commit('SET_ROLES', roles)resolve(data)}).catch(error => {reject(error)})})},// user logoutlogout({ commit, state }) {return new Promise((resolve, reject) => {removeToken() // must remove token firstresetRouter()commit('RESET_STATE')resolve()// logout(state.token).then(() => {// removeToken() // must remove token first// resetRouter()// commit('RESET_STATE')// resolve()// }).catch(error => {// reject(error)// })})},// remove tokenresetToken({ commit }) {return new Promise(resolve => {removeToken() // must remove token firstcommit('RESET_STATE')resolve()})},// dynamically modify permissionsasync changeRoles({ commit, dispatch }, role) {const token = role + '-token'commit('SET_TOKEN', token)setToken(token)const { roles } = await dispatch('getInfo')resetRouter()// generate accessible routes map based on rolesconst accessRoutes = await dispatch('permission/generateRoutes', roles, { root: true })// dynamically add accessible routesrouter.addRoutes(accessRoutes)// reset visited views and cached viewsdispatch('tagsView/delAllViews', null, { root: true })}
}export default {namespaced: true,state,mutations,actions
}
2.4 修改getter.js
const getters = {sidebar: state => state.app.sidebar,device: state => state.app.device,token: state => state.user.token,avatar: state => state.user.avatar,name: state => state.user.name,roles: state => state.user.roles,permission_routers: state => state.permission.routes,
}
export default getters
2.5 修改index.js
import Vue from 'vue'
import Vuex from 'vuex'
import getters from './getters'Vue.use(Vuex)// https://webpack.js.org/guides/dependency-management/#requirecontext
const modulesFiles = require.context('./modules', true, /\.js$/)// you do not need `import app from './modules/app'`
// it will auto require all vuex module from modules file
const modules = modulesFiles.keys().reduce((modules, modulePath) => {// set './app.js' => 'app'const moduleName = modulePath.replace(/^\.\/(.*)\.\w+$/, '$1')const value = modulesFiles(modulePath)modules[moduleName] = value.defaultreturn modules
}, {})const store = new Vuex.Store({modules,getters
})export default store
2.3 修改permission.js
主要修改红框中的
import router from "./router";
import store from "./store";
import { Message } from "element-ui";
import NProgress from "nprogress"; // progress bar
import "nprogress/nprogress.css"; // progress bar style
import { getToken } from "@/utils/auth"; // get token from cookie
import getPageTitle from "@/utils/get-page-title";NProgress.configure({ showSpinner: false }); // NProgress Configurationconst whiteList = ["/login", "/funnelAnalyse", "/retentionAnalyse"]; // no redirect whitelistrouter.beforeEach(async (to, from, next) => {// start progress barNProgress.start();// set page titledocument.title = getPageTitle(to.meta.title);// determine whether the user has logged inconst hasToken = getToken();if (hasToken) {if (to.path === "/login") {// if is logged in, redirect to the home pagenext({ path: "/" });NProgress.done();} else {const hasRoles = store.getters.roles && store.getters.roles.length > 0if (hasRoles) {next();} else {try {// get user info// await store.dispatch("user/getInfo");// note: roles must be a object array! such as: ['admin'] or ,['developer','editor']const { roles } = await store.dispatch('user/getInfo')// generate accessible routes map based on rolesconst accessRoutes = await store.dispatch('permission/generateRoutes', roles)// dynamically add accessible routesrouter.addRoutes(accessRoutes)// hack method to ensure that addRoutes is complete// set the replace: true, so the navigation will not leave a history recordnext({ ...to, replace: true })// next();} catch (error) {// remove token and go to login page to re-login// await store.dispatch("user/resetToken");await store.dispatch('user/resetToken')Message.error('Has Error')next(`/login?redirect=${to.path}`)NProgress.done()}}}} else {/* has no token*/if (whiteList.indexOf(to.path) !== -1) {// in the free login whitelist, go directlynext();} else {// other pages that do not have permission to access are redirected to the login page.next(`/login?redirect=${to.path}`);NProgress.done();}}
});router.afterEach(() => {// finish progress barNProgress.done();
});
参考
vue-admin-template 添加权限控制路由功能_fiskeryang的专栏-CSDN博客vue-element-template添加权限控制路由功能vue-element-template添加权限控制路由功能1、 变更@/router/index.js2、添加@/store/modules/permission.js3、改造数据库与实体4、@/store/modules/user.js5、更新 getter.js 和 index.js6、变更 @/permission.jsvue-element-template添加权限控制路由功能vue-element-template 是没有实现路由权https://blog.csdn.net/fiskeryang/article/details/112358889
Vue 增加动态路由功能 【在原有系统上增加】相关推荐
- vue将每个路由打包成html,Ant Design Vue pro 动态路由的实现和打包
Ant Design Vue pro 动态路由的实现和打包 Ant Design Vue pro 动态路由的实现和打包 配置路由权限 在config文件夹下router.config.js中配置路由权 ...
- Spring Cloud Alibaba 集成 Gateway 实现动态路由功能
文章目录 1 摘要 2 核心 Maven 依赖 3 名词释义 4 Gateway 动态路由原理 5 数据库表 6 核心代码 6.1 配置信息 6.2 路由实体类 6.3 本地路由数据库持久层(DAO/ ...
- 路由原理及vue实现动态路由
路由原理 在前端开发中,路由通常用于实现 SPA 应用程序,即在一个页面中切换不同的内容或页面,而不需要重新加载整个页面.路由的实现原理是通过监听 URL 的变化,然后根据不同的 URL 加载不同的内 ...
- vue admin 动态路由权限管理
主要思路 通过后端接口返回数据 进行判断 (通过后端实现的权限管理有许多种),在这里 我们主要通过 关键字即匹配前端路由meta.menu值来实现权限管理通常会把路由权限列表存至vux中 箭头所指的便 ...
- vue 实现动态路由
1.什么是动态路由? 2.动态路由的好处 3.动态路由如何实现 1.什么是动态路由? 动态路由,动态即不是写死的,是可变的.我们可以根据自己不同的需求加载不同的路由,做到不同的实现及页面的渲染.动态的 ...
- 【vue】---动态路由传值
vue中的路由传值动态路由1.在定义路由的时候通过/:属性的方式来定义传递参数的属性2.在进行路由跳转的时候通过/值得方式进行传递数据3.在需要接收参数的组件中通过this.$route.params ...
- Nginx部署Vue项目动态路由刷新404
目录 前言 第一次 第二次 前言 记录下Nginx部署Vue项目刷新404的解决方案,遇到了两次,route用的是history路由模式,动态路由: {path: '/article/:blogId' ...
- vue的动态路由(登录之后拿到动态路由通过addRouters()动态添加路由)
登录后我们拿到路由动态路由,后端传的数据可能为这个 {path: '/index',meta: {title: '首页',icon: 'icon-shouye',tab_index: 0, //给头部 ...
- vue实现动态路由一步到位
最近在写vue项目,需要由后台传来当前用户对应权限的路由表,前端通过调接口拿到后处理(后端处理路由),就是配置vue动态路由啦. 由于错信了一些网上的文章:(,导致在这个问题上耗费了不少时间,想想,还 ...
最新文章
- GeoTrust 企业(OV)型 SSL证书
- python中的seth函数_Python入门——turtle库的使用
- python while循环和双重循环
- 浅谈c/c++typedef和#define区别[转]
- exxi6.7如何传文件到win7_比QQ直传快100倍!它让PC、安卓、iPhone光速互传文件
- mysql udb_MySQL InnoDB的一些参数说明
- [vue-cli]在使用vue-cli开发vue项目时,自动刷新页面的原理你了解吗?
- 鸿蒙轻内核虚拟内存基础知识:虚拟内存进程空间编号
- 重要性采样(Importance Sampling)简介和简单样例实现
- 只十分钟,唾手可得的工作机会就被我搞砸了!
- android的log.v,Android Log.v(),Log.d(),Log.i(),Log.w(),Log.e() - 何时使用每一个?
- 常用SFTP工具类(多个公用方法)
- java 防止js注入----ESAPI结合Top10安全开发实战
- 在夕阳再晨的日子里(二)----掌管市场部的岁月之合作团队与社区的拓展
- 网络在线播放ASF格式流媒体文件的制作(转)
- 如何定制allure报告的logo
- 无论如何,我喜欢过你
- java around_java - 使用Spring AOP时,在单个连接点上具有参数绑定的多个Around建议会导致错误 - 堆栈内存溢出...
- Windows11之Vim超详细下载安装与使用教程
- 密码学系列之七:数字签名