后台管理系统路由鉴权(Vue2)

  1. 在前端项目当中,尤其是一些后台管理系统会涉及到路由的权限问题。不同的用户所能访问的菜单是不一样的,也有一些不一样的操作,今天的话喝大家分享一下关于在vue2项目中路由的权限。

  2. 一般情况我们前端会在roter里面定义一个静态路由,这个路由是任何登录过的用户都能访问的路由,比如说home、login

router文件夹下面的index.js

js 复制代码
import Router from 'vue-router'
import vue from "vue"

// 静态路由 也就是只要你登录了 不管你是什么权限 都能够访问的路由
const constantRoutes=[
    {
        name:'home',
        path:'/home',
        component:()=>import('@/views/home')
    },
    {
        name:'login',
        path:'/login',
        component:()=>import('@/views/login')
    },
]

export default new Router({
  mode: "history", // 去掉url中的#
  scrollBehavior: () => ({ y: 0 }),

  routes: constantRoutes
})


/// 在main.js 中去引入并且使用

import router from "./router";
new Vue({
  el: "#app",
  router,
  store,
  render: (h) => h(App),
});
  1. 然后就可以访问这两个路由了, 权限一般是后端处理,我们前端需要把当前用户登录的id或者是其他的标识,通过一个接口发送给后端,然后后端会给我们返回一个路由表类似于一个数组。类似于这样,id代表当前路由的id, pid为对应的上级路由id,(就是他爸爸的id)若pid为0则当前路由为一级路由(没有爸爸),很明显学生添加的id为2 pid为1,所以学生添加是学生管理的子路由, 学生管理的pid为0 所以学生管理为一级路由。
js 复制代码
[
    {
        "id": 1, // 代表我们路由id
        "pid": "0",// 上级id 0 代表一级路由
        "name": "student",
        "path": "/student",
        "title": "学生管理"
    },
    {
        "id": 2,
        "pid": "1",
        "name": "studentAdd",
        "path": "/student/studentAdd",
        "title": "学生添加"
    },
    {
        "id": 3,
        "pid": "2",
        "name": "studentDetail",
        "path": "/student/studentDetail",
        "title": "学生详情"
    },
    {
        "id": 4,
        "pid": "1",
        "name": "studentDelete",
        "path": "/student/studentDelete",
        "title": "学生删除"
    },
    {
        "id": 5,
        "pid": "0",
        "name": "teacher",
        "path": "/teacher",
        "title": "教师管理"
    },
    {
        "id": 6,
        "pid": "5",
        "name": "teacherAdd",
        "path": "/teacher/teacherAdd",
        "title": "教师新增"
    },
    {
        "id": 6,
        "pid": "5",
        "name": "teacherDelete",
        "path": "/teacher/teacherDelete",
        "title": "教师删除"
    }
]
  1. 我们前端拿到这样的数据之后会进行数据格式的处理, 渲染成路由树。下面我们在util文件夹下的index.js中定义一个transformTree函数
js 复制代码
// 转为树结构
function transformTree(routes) {

// 根据id 首先区分一级路由和子路由
    const parents = routes.filter(p => p.pid == 0)
    const children = routes.filter(p => p.pid != 0)
    
    calcRouteTree(parents, children)
    // 处理
    function calcRouteTree(parents, children) {
        parents.map(p => {
            children.map((c, i) => {
                if (c.pid == p.id) { // 代表c路由是p的儿子路由

                    
                    //深拷贝防止数据污染
                    let _c = JSON.parse(JSON.stringify(children))
                    _c.splice(i, 1) // 排他操作 

                    // 把当前子路由作为parent  其他的子路由作为children
                    calcRouteTree([c], _c)
                       
                     // 这一步得好好的理解 一开始接触的话可能有点绕  自己拿一个简单的例子好好体会
                    if (p.children) {
                        p.children.push(c)
                    } else {
                        p.children = [c]
                    }
                }
            })
        })
    }

    return parents
}
  1. 经过上面的处理我们可以得到类似与这样的数据,变成我们熟知的数据格式了
js 复制代码
[

    {
        "id": 1, // 代表我们路由id
        "pid": "0",// 上级id 0 代表一级路由
        "name": "student",
        "path": "/student",
        "title": "学生管理",
        children: [
            {
                "id": 2,
                "pid": "1",
                "name": "studentAdd",
                "path": "/student/studentAdd",
                "title": "学生添加",
                children: [
                    {
                        "id": 3,
                        "pid": "2",
                        "name": "studentDetail",
                        "path": "/student/studentDetail",
                        "title": "学生详情"
                    }
                ]
            },
            {
                "id": 4,
                "pid": "1",
                "name": "studentDelete",
                "path": "/student/studentDelete",
                "title": "学生删除"
            },
        ]
    }
]
  1. 上面一步是转为树结构,当然还不是我们真正需要的路由,我们还需要另外一个calcTureRoute函数帮我们处理。这个函数是将我们的树结构真正的转化为路由表, 说白了就是加一个component属性,以后可以用router.addRoutes(routes) 添加到我们的路由当中
js 复制代码
function calcTureRoute(routes) {

    const result = routes.map(item => {

        const data = {
            name: item.name,
            path: item.path,
            component:()=>import(`@/views/${item.name}`)
        }

        if (item.children) {
            data.children = calcTureRoute(item.children)
        }

        return data
    })


    return result

}
  1. 我们什么时候动态添加路由呢?下面我们来做一下路由守卫, 新建一个premiss.js文件夹,在main.js当中引入,引入代表把这个稳健执行一次。 我们把用户的信息都存储在vuex中,
js 复制代码
# vuex 仓库
import {transformRouteTree,calcTureRoute } from '@/utils/index.js' // 上面讲到的两个函数


const state
   state={
       userInfo:{},
       routerTree:[]
   }
}

const mutations={
           setUserInfo(state,userInfo){
           state.userInfo=userInfo
           },
           setRouterTree(state,tree){
           state.routerTree=tree
           },
   },
 
const actions={
   async getUserInfo({commit,state}){
       // 1. 获取用户数据
       const userInfo={name:"张三",token:"123456",role:"admin"}//  这里的数据是我写假数据,应该是要用接口拿
    
       commit('setUserInfo',userInfo) //数据拿完之后存储用户信息到user仓库
       
       setToken('token',userInfo.token) // 存入token到cooke中
       
       //2. 接下来获取权限路由数据 将来用接口拿的
       const paylod=[数据] // 后端接口数据 这里的数据是第三部分的数据  上面已经讲到了
           
       //3. 渲染树结构
        const result= transformRouteTree(paylod)
        
        commit('setRouterTree',result) //存储到user仓库中
     
       
   }
   
 
Premissioin.js 文件

import router from "vue-router"
import store  from './store' // 引入仓库
import {getToken,setToken}




router.beforeEach((to,from ,next)=>{

// 已经登录
if (getToken()) { // 登录成功时候获取用户信息的时候 就存入到了cookie当中

    if (to.path = "/login") {
        next({ path: '/' }) //已经登录 不能在跳转到登录
    } else {

        if (!store.state.user.info) {
            // 这里防止页面刷新 vuex丢失数据 重新获取一遍用户
            的信息
            //数据没了重新获取一遍数据 
            await store.dispatch('getUserInfo')  // 为什么要await一下呢 就是为了后端路由数据拿回来 前端处理完毕之后 

            // 现在user仓库中已经有了 routerTree结构 接下来我们渲染成真正的路由
            const routes = calcTureRoute(store.state.user.routerTree结构)

            router.addRouters(routes)  // 加入动态路由

        } else {
            next() //已经登录了 没有刷新页面 正常放行

        }

    }
} else {

    // 如果没有登录 先看看你走的是不是白名单,就是说你不用登录就可以访问的路由,一般的话有注册、首页等等

    const whiteList = ['/home', '/register'] // 举两个例子

    if (whiteList.includes(to.path)) {
        // 如果用户没有登录 去到的是白名单当中的路由就放行
        next()
    } else {
        //否则你既没有登录 也不是去的白名单路由 就跳转到登录
        next({ path: '/login' })
    }
}
)


}

注意点:

  1. 唯一难以理解的就是上面给出的递归函数,这个得好好的琢磨。
  2. 页面刷新的时候,会导致仓库的数据清空,有token情况下用户数据没了,在仓库中再次请求一次用户数据就行了。
  3. 每次路由跳转都会执行beforeEach函数, 把你小子拦截下来 自己盘问一番。就是这个意思
  4. 根据user仓库中的routerTree去渲染Menu菜单列表,这个作者就不赘述了。

路由鉴权大致的思想就是这样,上面给出了部分代码,一定要结合到实际项目当中去。本文出自作者本人实际经验。若有错误多多指正! 感谢支持。

相关推荐
亚里士多没有德7752 分钟前
强制删除了windows自带的edge浏览器,重装不了怎么办【已解决】
前端·edge
micro2010145 分钟前
Microsoft Edge 离线安装包制作或获取方法和下载地址分享
前端·edge
.生产的驴10 分钟前
Electron Vue框架环境搭建 Vue3环境搭建
java·前端·vue.js·spring boot·后端·electron·ecmascript
awonw13 分钟前
[前端][easyui]easyui select 默认值
前端·javascript·easyui
老齐谈电商15 分钟前
Electron桌面应用打包现有的vue项目
javascript·vue.js·electron
LIURUOYU42130828 分钟前
vue.js组建开发
vue.js
九圣残炎33 分钟前
【Vue】vue-admin-template项目搭建
前端·vue.js·arcgis
《源码好优多》1 小时前
基于SpringBoot+Vue+Uniapp的植物园管理小程序系统(2024最新,源码+文档+远程部署+讲解视频等)
vue.js·spring boot·uni-app
柏箱1 小时前
使用JavaScript写一个网页端的四则运算器
前端·javascript·css
TU^1 小时前
C语言习题~day16
c语言·前端·算法