Vue实现动态路由

这篇具有很好参考价值的文章主要介绍了Vue实现动态路由。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

前言

一、项目介绍

1.开发环境

2.功能

3.项目运行截图  

二、实现

1.动态路由如何实现

2.项目目录介绍

3.核心代码

4.坑和知识点

小结


前言

最近在学权限相关的管理项目,前端用到了动态路由,就是根据用户角色显示不同的菜单,动态添加路由。说着好像很简单,但看了很多教程,也跟着教程写了很多代码,但最后都跑不通(很多原因,比如:版本问题,教程没有全部代码,只有核心代码片段等)。😭😭😭所以,我只能狠下心,写下这篇博客,方便自己总结,也为了避免大家踩坑。

一、项目介绍

废话不多说,直接附上项目下载地址:
gitee:https://gitee.com/wusupweilgy/springboot-vue.git

蓝奏云:https://wwp.lanzoup.com/iO74W0r6bcob

1.开发环境

前端:vue2+element-ui组件

2.功能

根据用户的账号密码,生成不同的菜单,动态添加路由

3.项目运行截图  

generateroutes,SpringBoot+Vue实现小功能,vue.js,前端,javascript

 generateroutes,SpringBoot+Vue实现小功能,vue.js,前端,javascript

二、实现

1.动态路由如何实现

流程:

  1. 登录的时候,根据登录用户返回此角色可以访问的页面的路由和token
  2. 前端将路由存储到sessionStorage和vuex中(因为vuex存储的数据一刷就没了,所以需要配合sessionStorage)
  3. 在路由前置守卫处动态添加拿到的路由,对页面进行渲染。

2.项目目录介绍

generateroutes,SpringBoot+Vue实现小功能,vue.js,前端,javascript

  •  assets:存放图片和样式
  • router:路由配置
    • dynamicRoutes.js:动态路由模板
    • index.js:静态路由
    • permission.js:路由前置守卫
  • store:vuex存储全局的状态变量
  • util:工具类
    • index.js:动态添加路由工具类
    • request.js:axios请求工具类
  • views:存放页面

3.核心代码

1)/views/Login.vue:登录(onSubmit方法)成功时,根据用户名密码区分角色,根据角色将不同路由和token写入vuex,dynamicRoutes.js中有两个路由模板,分别是user和admin,然后调用generateRoutes()方法向vue-router中动态添加路由

import {admin,user} from '@/router/dynamicRoutes'
...

onSubmit(formName) {
    //为表单绑定验证功能
    this.$refs [formName].validate((valid) => {
        if (valid) {
            if(this.form.username==="user"&&this.form.password==="user"){
                store.commit('SET_MENULIST', user);
                store.commit('SET_TOKEN', 'user');
            }else if(this.form.username==="admin"&&this.form.password==="admin"){
                store.commit('SET_MENULIST', admin);
                store.commit('SET_TOKEN', 'admin');
            }else{
                this.$message.error("登录失败")
                return
            }
            this.$message.success("登录成功")
            generateRoutes()
            this.$router.replace('/')

        } else {
            this.dialogVisible = true;
            return false;
        }
    });
},

2)/store/index.js:vuex状态管理(配合sessionStorage)

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    token:'',
    menuList:[],
    isLoadRouters:false
  },
  getters: {
    GET_TOKEN:state => {
      state.token = sessionStorage.getItem("token")
      return state.token
    },
    GET_MENULIST:state => {
      state.menuList = JSON.parse(sessionStorage.getItem("menuList")||'[]')
      return state.menuList
    },
    GET_ISLOADROUTERS:state=>{
      return state.isLoadRouters
    }
  },
  mutations: {
    SET_TOKEN:(state,token)=>{
      state.token = token
      sessionStorage.setItem("token",token);
    },
    SET_MENULIST:(state,menuList)=>{
      state.menuList = menuList
      sessionStorage.setItem("menuList",JSON.stringify(menuList));
    },
    SET_ISLOADROUTERS:(state,isLoadRouters)=>{
      state.isLoadRouters = isLoadRouters
    }
  },
})

3)/util/index.js:方法动态添加路由工具

import router from '../router'
import store from '@/store'

//动态添加路由
export function generateRoutes() {
    const _asyncRoutes = store.getters.GET_MENULIST
    if(_asyncRoutes==null)
        return
    _asyncRoutes.forEach(menu => {
        if (menu.children) {
            menu.children.forEach(m => {
                let route = menuToRoute(m, menu.name);
                if (route) {
                    router.addRoute("Home",route)
                }
            })
        }
    })
}

//将菜单转换成router可以识别的路由
const menuToRoute = (menu, parentName) => {
    if (!menu.component) {
        return null;
    } else {
        let route = {
            name: menu.name,
            path: menu.path,
            meta: {
                parentName: parentName
            }
        }
        route.component = () => import('@/views/' + menu.component + '.vue');
        return route;
    }
}

4)/router/permission.js前置路由守卫,判断是否登录和是否已经添加过路由

import router from "@/router/index"
import store from "@/store"
import {generateRoutes} from "@/util";

// 检查是否存在于免登陆白名单
function inWhiteList(toPath) {
    const whiteList = ['/login', '/404']
    const path = whiteList.find((value) => {
        // 使用正则匹配
        const reg = new RegExp('^' + value)
        return reg.test(toPath)
    })
    return !!path
}

router.beforeEach((to, from, next) => {
    console.group('%c%s', 'color:blue', `${new Date().getTime()}  ${to.path} 的全局前置守卫----------`)
    console.log('所有活跃的路由记录列表', router.getRoutes())
    console.groupEnd()
    const token = store.getters.GET_TOKEN
    let isLoadRouters = store.state.isLoadRouters
    if (inWhiteList(to.path)) {
        next()
    } else {
        //用户已登录
        if (token && JSON.stringify(store.getters.GET_MENULIST) !== '[]') {
            if (isLoadRouters) {
                // console.log('路由已添加,直接跳转到目标页面');
                next()
            } else {
                //解决刷新页面空白
                //console.log('重新加载路由,并跳转到目标页');
                let menuList = store.getters.GET_MENULIST
                store.commit('SET_ISLOADROUTERS', true)
                //添加动态路由
                generateRoutes(menuList)

                next({...to, replace: true})
            }
        } else {
            // console.log('无登录信息,跳转到登录页');
            store.commit('SET_ISLOADROUTERS', false)
            next(`/login`)
        }
    }

})

4.坑和知识点

1)遇到的坑

  • 这里有个大坑,就是页面刷新的情况,页面一旦刷新,动态添加的路由也会清空,只剩静态路由,所有还要判断页面刷新的操作,这里通过一个vuex的变量解决,因为刷新操作,vuex的值也会刷新,所以我在vuex中设置了isLoadRouters:false这个变量,如果刷新,这个值就是默认的false
  • 第二个坑就是,在addRoute()之后第一次访问被添加的路由会白屏,这是因为刚刚addRoute()就立刻访问被添加的路由,然而此时addRoutes()没有执行结束,因而找不到刚刚被添加的路由导致白屏。因此需要从新访问一次路由才行,所以需要next({...to, replace: true}),来保证路由添加完了再进入页面 (可以理解为重进一次)。小伙伴可以试试把它换成next(),看会不会出现白屏。是

这两个坑就已经卡了我很长时间了,更何况还有其他小坑(哭死我了)

  • 用户点击退出后,需要重置路由,不然你添加过路由了,再通过addRoute()方法添加路由就会造成重复添加路由,浏览器的控制台会有警告,不重置也没事,就是看着有点不舒服。

// 重置路由
export function resetRouter() {
    const newRouter = createRouter()
    router.matcher = newRouter.matcher
}

2)学到的知识点

  • js语法:两个感叹号,将非布尔型变量转为布尔值

// 检查是否存在于免登陆白名单
function inWhiteList(toPath) {
    const whiteList = ['/login', '/404']
    const path = whiteList.find((value) => {
        // 使用正则匹配
        const reg = new RegExp('^' + value)
        return reg.test(toPath)
    })
    return !!path
}
  • component: () => import("@/views/Index") 实现路由组件懒加载。vue这种单页面应用单页面应用单页面应用,如果我们不去做路由懒加载,打包之后的文件将会异常的大,就会造成进入首页时,需要加载的内容过多,时间过长,会出现长时间的白屏,不利于用户体验,运用懒加载就可以将页面进行划分,需要的时候加载页面,可以有效的分担首页所承担的加载压力,减少首页加载用时。
  • next({...to, replace: true}) 重新访问一次路由,避免路由还没添加完成就访问路
  • router.matcher = newRouter.matcher相当于重置路由,避免重复添加路由

小结

本文介绍了使用Vue实现动态路由。关于这个东西,我网上找的很多教程都不怎么靠谱,给我挖了很多坑,所以希望我的这篇教程可以帮助你,少走点弯路,快速掌握这技术,代码的下载地址在文章开头,记得npm install一下,就可以运行了。如果这篇文章有幸帮助到你,希望读者大大们可以给作者给个三连呀😶‍🌫️😶‍🌫️😶‍🌫️文章来源地址https://www.toymoban.com/news/detail-737730.html

到了这里,关于Vue实现动态路由的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Vue实现动态路由【记录学习的快乐】

    1、什么是动态路由? 2、动态路由的好处 3、动态路由如何实现 1、什么是动态路由? 动态路由,动态即不是写死的,是可变的。我们可以根据自己不同的需求加载不同的路由,做到不同的实现及页面的渲染。动态的路由存储可分为两种,一种是将路由存储到前端。另一种则

    2024年02月07日
    浏览(22)
  • Vue从后端取数据,实现动态路由

            将获取菜单的方法放在全局中,以便每次刷新页面时,能够加载出。 this.$store.state.userInfo 是登入后存放在Vuex的用户信息  按照上面要求即可实现

    2024年01月20日
    浏览(25)
  • Vue如何实现权限管理(动态路由addRoutes)

    目录 引言 推荐B站视频 一、权限管理 二、控制权限 接口权限 路由权限控制 方法一 方法二 菜单权限 方法一 方法二 按钮权限 方法一 方法二 项目中会遇到权限管理,来让特定用户有特定权限的场景,那么怎么做这个权限管理,以及有多少办法呢,下面给大家絮叨 vue权限管

    2023年04月25日
    浏览(24)
  • vue实现动态路由添加(简单无废话版本)

    最近练习vue的项目,有关于后台管理系统的动态添加路由部分,根据思路实现了基本的功能,在这里记录一下,等后面学习后在进行优化。 这里只是记录我个人最后实现的思路,本人由于是初学者,可能思路和代码有不正确地方,还求多见谅。也请能不吝赐教,一同进步。 我

    2023年04月08日
    浏览(24)
  • vue3实现动态菜单和动态路由和刷新后白屏处理

    项目中,当每一个角色得到的界面不一致的时候,我们就不能使用静态菜单了,而是要从后端得到动态的菜单数据,然后动态的将菜单数据展示在界面上。 除了在界面展示,也还要将界面的路由动态添加,在路由动态添加之后,你可能会出现刷新界面,界面变白的情况,页面

    2024年02月06日
    浏览(32)
  • Vue+SpringBoot实现评论功能

    评论系统相信大家并不陌生,在社交网络相关的软件中是一种常见的功能。然而对于初学者来说,实现一个完整的评论系统并不容易。本文笔者以 Vue+SpringBoot 前后端分离的架构细说博客评论功能的实现思路。 对于一个评论系统主要包含评论人,评论时间,评论内容,评论回

    2023年04月08日
    浏览(33)
  • vue + less 实现动态主题换肤功能

    在vue项目中(我的是2.6.11版本的)使用less做到切换主题肤色。话不多说,直接开始。 我这里的项目是2.6.11版本的 安装一些less的插件 路径: src assets style theme 翻译:theme 的中文就是主题 注意点:考虑到切换样式也是样式中的,所以放在style里面,当然, 你可以放在任意位置

    2024年02月12日
    浏览(20)
  • SpringBoot+Vue实现文件上传功能

    目录 1.后端代码部分: 2.前端代码部分 3.效果展示 1.后端代码部分: 2.前端代码部分 3.效果展示      

    2024年02月12日
    浏览(33)
  • SpringBoot+Vue实现一个系统登录功能

    1. 创建一个Spring Boot项目,添加Web和Security依赖。 2. 创建一个User实体类,用于存储用户信息。 3. 创建一个UserDetailsService接口的实现类,用于加载用户信息。 4. 创建一个WebSecurityConfig类,继承WebSecurityConfigurerAdapter,并重写configure方法,配置SpringSecurity。 5. 在Vue项目中创建一个

    2024年01月15日
    浏览(25)
  • SpringBoot+Vue实现简单的登录注册功能

    😶‍🌫️😶‍🌫️😶‍🌫️如果你是一名全干程序员,那前后端跨域问题一定是家常便饭,作者今天带大家写一个最简单的前后端分离登录系统,方便我们理解前后端分离项目的跨域以及数据传输问题。因为要照顾小白,所以我会写的详细一点,不足的地方,大家多多指

    2024年02月04日
    浏览(25)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包