登录->获取token存储->获取路由信息,动态添加路由
1.路由
路由文件可分为常显路由,比如login,404页面
router.js
import Vue from "vue";
import Router from "vue-router";
Vue.use(Router);
/* Layout */
import Layout from "@/layout";
export const constantRoutes = [
{
path: "/login",
component: () => import("@/views/login/index"),
hidden: true,
},
{
path: "/404",
component: () => import("@/views/404"),
hidden: true,
},
{
path: "/",
component: Layout,
redirect: "/dashboard",
children: [
{
path: "dashboard",
name: "Dashboard",
component: () => import("@/views/dashboard/index"),
meta: { title: "Dashboard", icon: "s-tools" },
},
],
},
];
const createRouter = () =>
new Router({
mode: "history", // require service support
scrollBehavior: () => ({ y: 0 }),
routes: constantRoutes,
});
const router = createRouter();
const originalPush = Router.prototype.push;
Router.prototype.push = function push(location, onResolve, onReject) {
if (onResolve || onReject)
return originalPush.call(this, location, onResolve, onReject);
return originalPush.call(this, location).catch((err) => err);
};
export function resetRouter() {
const newRouter = createRouter();
router.matcher = newRouter.matcher; // reset router
}
export default router;
2.权限路由js文件,permission.js
主要内容如下:
1.const hasToken = getToken();
这块就是一开始我们登录成功,存储在local stroage里面的token
2. const hasGetRoleList = store.getters.roleList.length;
const getters = {
roleList: state => state.user.roleList,
}
export default getters
这块是我们获取接口权限路由列表返回数据
3.const roles = await store.dispatch("user/getInfo");
这块是我们请求路由权限列表的接口
我这里没有走真实接口,直接mock了数据
import list from "@/routeMock/data";
const state = {
roleList: [], // 用于获取到的权限数据
};
const mutations = {
SET_ROLELIST: (state, payload) => {
state.roleList = payload;
},
};
const actions = {
// 获取侧边栏权限列表
getInfo({ commit, state }) {
return new Promise((resolve, reject) => {
commit("SET_ROLELIST", list);
resolve(list);
});
},
};
export default {
namespaced: true,
state,
mutations,
actions,
};
4.convertMenuFormat方法,这个方法是将后端返回的数据,转换为正常我们页面需要的route.js里面写的结构。主要注意点:1.父节点conponent为Layout的问题,2.子节点加载.vue文件路径的问题
引入:import Layout from "@/layout";主界面代码结构如下:
import Layout from "@/layout";
//....中间省略转换过程
//核心内容是这边的转换
if (menu.type === 1) {
// 目录
converted.component = Layout;
converted.redirect = menu.path;
} else if (menu.type === 2) {
// 菜单
converted.component = () => import(`@/views${menu.path}.vue`);
}
5.动态添加路由到router对象中
const routes = convertMenuFormat(roles);
routes.forEach((item) => {
router.options.routes.push(item);
router.addRoute(item);
});
router.addRoute({ path: "*", redirect: "/404", hidden: true });
完整permission。js代码如下
import router from "./router";
import store from "./store";
import { Message } from "element-ui";
import NProgress from "nprogress";
import "nprogress/nprogress.css";
import { getToken } from "@/utils/auth";
import { filterASyncRoutes ,convertMenuFormat} from "@/page-utils/formateRoutes";
NProgress.configure({ showSpinner: false });
const whiteList = ["/login"];
router.beforeEach(async (to, from, next) => {
NProgress.start();
document.title = to.meta.title || "vue Admin Template";
const hasToken = getToken();
console.log('hasToken:', hasToken);
if (hasToken) {
if (to.path === "/login") {
next({ path: "/" });
NProgress.done();
} else {
const hasGetRoleList = store.getters.roleList.length;
console.log('hasGetRoleList:', hasGetRoleList);
if (hasGetRoleList) {
next();
} else {
try {
// 获取权限列表
const roles = await store.dispatch("user/getInfo");
// 将获得的权限列表,组装成router需要的类型
const routes = convertMenuFormat(roles);
routes.forEach((item) => {
router.options.routes.push(item);
router.addRoute(item);
});
router.addRoute({ path: "*", redirect: "/404", hidden: true });
next({ ...to, replace: true });
} catch (error) {
await store.dispatch("user/resetToken");
Message.error({
message: error || "Has Error",
});
console.log("error: ", error);
next(`/login?redirect=${to.path}`);
NProgress.done();
}
}
}
} else {
if (whiteList.indexOf(to.path) !== -1) {
next();
} else {
next(`/login?redirect=${to.path}`);
NProgress.done();
}
}
});
router.afterEach(() => {
NProgress.done();
});
侧边栏使用代码如下:
computed: {
routes() {
return this.$router.options.routes;
},
activeMenu() {
const route = this.$route;
const { meta, path } = route;
if (meta.activeMenu) {
return meta.activeMenu;
}
return path;
},
},
路由拼接数据结构内容: