vue【路由导航守卫控制访问主页前先登录】--实现用户登录及token验证----以及使用NProgress
参考:
实现用户登录及token验证:
https://blog.csdn.net/qzcrystal/article/details/106884810
https://www.cnblogs.com/tt-ff/p/11736463.html
NProgress使用参考:
https://blog.csdn.net/wn1245343496/article/details/82151273
官网:http://ricostacruz.com/nprogress/
github:https://github.com/rstacruz/nprogress
主要用到导航守卫:
与main.js同级的 permission.js:
import router from './router'; import store from './store'; import NProgress from 'nprogress'; import 'nprogress/nprogress.css'; import { Message } from 'element-ui'; import { getToken } from '@/utils/auth'; // 验权从cookie中获取 import { getUserInfo } from '@/api/user'; import { setTitle } from '@/utils/mUtils'; // 设置浏览器头部标题 function hasPermission(roles, permissionRoles) { if (roles.indexOf('admin') >= 0) { return true; } if (!permissionRoles) { return true; } return roles.some(role => permissionRoles.indexOf(role) >= 0); } const whiteList = ['/login']; // 不重定向白名单 router.beforeEach((to, from, next) => { NProgress.start(); // 设置头部浏览器标题 const browserHeaderTitle = to.meta.title; store.commit('SET_BROWSERHEADERTITLE', { browserHeaderTitle: browserHeaderTitle }); // 点击登录时拿到了token,并存入了了cookie,保证页面刷新时,始终可以拿到token if (getToken('Token')) { if (to.path === '/login') { next(); NProgress.done(); } else { // 用户登录成功之后,每次点击路由都进行角色的判断 if (store.getters.roles.length === 0) { const token = getToken('Token'); getUserInfo({ token: token }) .then(res => { console.log(res); const userList = res.data.userList; store.commit('SET_ROLES', userList.roles); store.commit('SET_NAME', userList.name); store.commit('SET_AVATAR', userList.avatar); store .dispatch('GenerateRoutes', { roles: userList.roles }) .then(() => { // 根据roles权限生成可访问的路由表 router.addRoutes(store.getters.addRouters); // 动态添加可访问权限路由表 next({ ...to, replace: true }); // hack方法,确保addRoutes已经完成 }); }) .catch(err => { store.dispatch('LogOut').then(() => { Message.error(err || 'V;erification failed, please login again'); next({ path: '/login' }); }); }); } else { // 没有动态改编权限的需求可直接next() 删除下方权限判断 if (hasPermission(store.getters.roles, to.meta.roles)) { next(); } else { next({ path: '/401', replace: true, query: { noGoBack: true } }); } } } } else { if (whiteList.indexOf(to.path) !== -1) { // 点击退出时,会定位到这里 next(); } else { next('/login'); NProgress.done(); } } }); router.afterEach(() => { NProgress.done(); setTimeout(() => { const browserHeaderTitle = store.getters.browserHeaderTitle; setTitle(browserHeaderTitle); }, 0); });
main.js:
import '@/permission.js';
路由:router:index.js
import Vue from "vue"; import Router from "vue-router"; import { Layout, Content } from "../layout"; // 页面整体布局 import { topRouterMap } from "./topRouter"; process.env.NODE_ENV === "development" ? Vue.use(Router) : null; function filterTopRouterMap(name) { let router = topRouterMap.find((item) => { return item.parentName === name; }); return router.data; // arr } /** * 1、roles:后台返回的权限结构; * */ //手动跳转的页面白名单 const whiteList = ["/"]; /** * path:''与path:'*'的区别: * 1、path:'*', 会匹配所有路径 * 2、path:'',也是会匹配到路由 * */ //默认不需要权限的页面 export const constantRouterMap = [ { path: "", component: Layout, redirect: "/index/index", hidden: true, }, { path: "/login", name: "login", component: () => import("@/page/login"), hidden: true, }, { path: "/404", component: () => import("@/page/errorPage/404"), hidden: true, }, { path: "/401", component: () => import("@/page/errorPage/401"), hidden: true, }, { path: "/index", name: "index", component: Layout, meta: { title: "首页", icon: "icondashboard", }, noDropdown: true, children: [ { path: "index", meta: { title: "首页", icon: "icondashboard", routerType: "leftmenu", }, component: () => import("@/page/index/index"), }, ], }, ]; //注册路由 export default new Router({ mode: "history", // 默认为'hash'模式 base: "/permission/", // 添加跟目录,对应服务器部署子目录 routes: constantRouterMap, }); //异步路由(需要权限的页面) export const asyncRouterMap = [ { path: "/userManager", name: "userManage", component: Layout, meta: { title: "用户管理", icon: "iconuser", }, noDropdown: true, children: [ { path: "userList", meta: { title: "用户管理", icon: "iconuser", routerType: "leftMenu", }, component: () => import("@/page/userList/userList"), }, ], }, { path: "/share", name: "share", component: Layout, meta: { title: "分享功能", icon: "iconshare", }, noDropdown: true, children: [ { path: "share", meta: { title: "分享功能", icon: "iconshare", routerType: "leftMenu", }, component: () => import("@/page/share"), }, ], }, { path: "/infoManage", name: "infoManage", meta: { title: "信息管理", icon: "iconinfo", }, component: Layout, children: [ { path: "infoShow", name: "infoShow", meta: { title: "个人信息", icon: "iconinfo", routerType: "leftMenu", titleList: [ { path: "infoShow1", title: "个人信息子菜单1" }, { path: "infoShow2", title: "个人信息子菜单2" }, { path: "infoShow3", title: "个人信息子菜单3" }, { path: "infoShow4", title: "个人信息子菜单4" }, { path: "infoShow5", title: "个人信息子菜单5" }, ], }, component: Content, children: filterTopRouterMap("infoShow"), }, { path: "infoModify", name: "infoModify", meta: { title: "修改信息", icon: "iconinfo", routerType: "leftmenu", titleList: [ { path: "infoModify1", title: "修改信息子菜单1" }, { path: "infoModify2", title: "修改信息子菜单2" }, { path: "infoModify3", title: "修改信息子菜单3" }, ], }, component: Content, children: filterTopRouterMap("infoModify"), }, ], }, { path: "/fundManage", name: "fundManage", meta: { title: "资金管理", icon: "iconpay3", }, component: Layout, children: [ { path: "fundList", name: "fundList", meta: { title: "资金流水", routerType: "leftmenu", }, component: () => import("@/page/fundList/fundList"), }, { path: "chinaTabsList", name: "chinaTabsList", meta: { title: "区域投资", routerType: "leftmenu", }, component: () => import("@/page/fundList/chinaTabsList"), }, ], }, { path: "/fundData", name: "fundData", meta: { title: "资金数据", icon: "iconecharts", }, component: Layout, redirect: "/fundData/fundPosition", children: [ { path: "fundPosition", name: "fundPosition", meta: { title: "投资分布", }, component: () => import("@/page/fundData/fundPosition"), }, { path: "typePosition", name: "typePosition", meta: { title: "项目分布", }, component: () => import("@/page/fundData/typePosition"), }, { path: "incomePayPosition", name: "incomePayPosition", meta: { title: "收支统计", }, component: () => import("@/page/fundData/incomePayPosition"), }, ], }, { path: "/permission", name: "permission", meta: { title: "权限设置", icon: "iconpermission", roles: ["admin", "editor"], // you can set roles in root nav }, component: Layout, redirect: "/permission/page", children: [ { path: "page", name: "pagePer", meta: { title: "页面权限", roles: ["admin"], // or you can only set roles in sub nav }, component: () => import("@/page/permission/page"), }, { path: "directive", name: "directivePer", meta: { title: "按钮权限", roles: ["editor"], }, component: () => import("@/page/permission/directive"), }, ], }, { path: "/error", component: Layout, name: "errorPage", meta: { title: "错误页面", icon: "iconError", }, children: [ { path: "401", name: "page401", component: () => import("@/page/errorPage/401"), meta: { title: "401", noCache: true, }, }, { path: "404", name: "page404", component: () => import("@/page/errorPage/404"), meta: { title: "404", noCache: true, }, }, ], }, { path: "*", redirect: "/404", hidden: true }, ]; /** * 路由设置要求: * 1、该路由有子菜单,可以设置多层嵌套路由children;如果没有子菜单,不需要设置children;通过item.children.length来判断路由的级数; * 2、登录成功后,定位到系统首页时,需要加载页面整体布局组件Layout并进行子路由定向加载; * * 按需加载路由组件的2种方法: * 1、component: () => import('@/page/login') * 2、component:resolve => require(['@/page/fundPosition'], resolve) * * * * 什么情况下,路由会定位到404页面? * 路由中redirect:'',不起作用? * 三级子菜单要在顶部展示? * * * */
记录自己的采坑之路,需要时方便查找