如何做制作头像的网站,微信小程序插件开发,网站哪里有,中国核工业第五建设有限公司成都分公司1.大概思路
设置基础路由login和home等页面#xff1b;登录后从后端获取user,token,rights等数据#xff0c;并将数据同时存储到vuex和sessionStorage中将后端获取的权限数据#xff08;作为不同用户显示不同菜单及不同路由的依据#xff09;和路由页面进行映射#xff1…1.大概思路
设置基础路由login和home等页面登录后从后端获取user,token,rights等数据并将数据同时存储到vuex和sessionStorage中将后端获取的权限数据作为不同用户显示不同菜单及不同路由的依据和路由页面进行映射写公共方法添加动态路由在路由全局守卫中判断是否已添加过动态路由如果已添加直接next()未添加调用添加动态路由方法并且放行next({ ...to, replace: true });添加动态路由位置第二种方法全局路由中只负责判断是否有动态路由和放行调用添加动态路由方法在登录后立即调用且以防页面手动刷新时进行404页面需要在App.vue的create()方法中再次调用
2.设置基础路由login页面Home页面等
//route.js
import { createRouter, createWebHistory } from vue-router
const routes [{ name: Login, path: /login, component: Login },{name: Home,path: /,component: Home,// 到home页面后直接跳转到excelPreview页面redirect: /uploadSpec?active0,meta: {authentication: true},// 整个页面为Home如果想要点击el-aside左侧菜单将对应路由内容显示在el-main区域需要将其他路由路径设置为Home的子路径且path前没有/children: [{name: UploadSpec,path: uploadSpec,title: 上传spec,component: UploadSpec,// 组件内传参meta: {keepAlive: true,authentication: true,// 用于设置tab名title: 上传spec,}},]},// vue3不再使用path:*正则匹配而是使用/pathMatch(.*)*或/pathMatch(.*)或/catchAll(.*)// { name: NotFound, path: /404, component: NotFound },// { path: /:pathMatch(.*), redirect: /404 },
];const router createRouter({history: createWebHistory(),routes,
});
2.从后端获取菜单权限数据并设置到vuex和sessionStorage中
这里使用mock模拟后端返回数据
//mock/user.js
import Mock from mockjsconst users [{id: 1, path:/uploadSpec,authName: 上传spec, icon: ,children:[]},{id: 2, path:/showSpec, authName: Spec预览, icon: ,children:[]},{id: 3, path:/generateTxt, authName: 生成测试数据, icon: ,children:[]},{id: 4, path:/generateCronjob, authName: 生成转码程序, icon: ,children:[]},{id: 5, path:/pdfCompare, authName: PDF文档对比, icon: ,children:[]},{id: 6, path:/resourceUpdate, authName: 资源更新管理, icon: ,children:[]},{id: 7, path:/generateTestCase, authName: 自动生成ST/SIT案例, icon: ,children:[]},{id: 8, path:/userManagement, authName: 用户管理, icon: User},
]Mock.mock(/user/login, Mock.mock({code: 200,success: true,data: {users: users,token: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwidXNlck5hbWUiOiJhZG1pbiIsIm5pY2tOYW1lIjoi6LaF566hIiwiaWNvbiI6IiIsInJvbGVJZCI6MSwic3ViIjoiYWRtaW4iLCJleHAiOjE2OTI3NzMzNTMsImp0aSI6ImZkNmVkOWZiMjdiYzQxODg5OWRmYmYzNzhlMTMzZmQ0In0.APGpN-i2edKwPQA52LP10aDEM2DZi7G71k8f_njGcpE}
})
)Mock.mock(/user/me, Mock.mock({code: 200,success: true,data: {id: 1,userName: admin,nickName: 超管,icon: ,roleId: 1,rights: users,}
})
)
3.登录后将数据存到vuex和sessionStorage中
//Login.vue await this.$store.dispatch(user/login, {...this.user}); //store/user/user.js
import * as api from /api/api
import { ElMessage } from element-plusconst state () {return {user:JSON.parse(sessionStorage.getItem(user) || {}),rights: JSON.parse(sessionStorage.getItem(rights) || [])}
}const getters () {}const actions {// 注意async位置和箭头函数写法login: async({ commit }, user) {// 调用登录接口try {let result await api.login(user);if (result.data.code 200) {sessionStorage.setItem(token, result.data.data.token);// 调用获取user信息接口let loginUser await api.getLoginUser();// 调用mutations的login方法if (loginUser.data.code 200) {commit(login, loginUser.data.data);} else {ElMessage.error(登录失败用户信息获取失败);}} else {ElMessage.error(登录失败 result.data.errorMsg);}} catch (error) {throw error;}},
}const mutations {initUser: (state) {// 从localStorage中获取数据设置进user中否则通过刷新页面时获取不到state中的user信息state.user JSON.parse(sessionStorage.getItem(loginUser));},login: (state, user) {// 登录成功后将user信息存到state中且缓存到localStorage中state.user user;state.rights user.rights;sessionStorage.setItem(loginUser, JSON.stringify(user));sessionStorage.setItem(rights, JSON.stringify(user.rights));},
}export default {namespaced: true,state,getters,actions,mutations
}
4.设置菜单权限数据和路由的映射
注意此处routeMapping的key和uploadSpecRule的path以及和后端返回数据rights的user.js的path必须一致且路径必须有 /
const uploadSpecRule {name: UploadSpec,path: /uploadSpec,title: 上传spec,component: UploadSpec,meta: {keepAlive: true,authentication: true,title: 上传spec,}
};const showSpecRule {name: ExcelPreview,path: /showSpec,title: Spec预览 | 生成测试数据,component: ExcelPreview,meta: {keepAlive: true,authentication: true,title: Spec预览,}
};const generateTxtRule {name: GenerateTxt,path: /generateTxt,title: 生成测试数据,component: GenerateTxt,meta: {keepAlive: true,authentication: true,title: 生成测试数据,}
};
const generateCronjobRule {name: GenerateCronjob,path: /generateCronjob,title: 生成转码程序,component: GenerateCronjob,meta: {keepAlive: true,authentication: true,title: 生成转码程序,}
};
const pdfCompareRule {name: PDFCompare,path: /pdfCompare,title: PDF文档对比,component: PDFCompare,meta: {keepAlive: true,authentication: true,title: PDF文档对比,}
};
const resourceUpdateRule {name: ResourceUpdate,path: /resourceUpdate,title: 资源更新管理,component: ResourceUpdate,meta: {keepAlive: true,authentication: true,title: 资源更新管理,}
};
const generateTestCaseRule {name: GenerateTestCase,path: /generateTestCase,title: 自动生成ST/SIT案例,component: GenerateTestCase,meta: {keepAlive: true,authentication: true,title: 自动生成ST/SIT案例,}
};
const userManagementRule {name: UserManagement,path: /userManagement,title: 用户管理,component: UserManagement,meta: {keepAlive: true,authentication: true,title: 用户管理,}
};const routeMapping {/uploadSpec: uploadSpecRule,/showSpec: showSpecRule,/generateTxt: generateTxtRule,/generateCronjob: generateCronjobRule,/pdfCompare: pdfCompareRule,/resourceUpdate: resourceUpdateRule,/generateTestCase: generateTestCaseRule,/userManagement: userManagementRule,
}5.设置可导出添加动态路由公共方法
export const initDynamicRoutes async () {const rightsList Store.state.user.rights;;rightsList.length 0 rightsList.forEach(item {if (item.path) {const temp routeMapping[item.path];router.addRoute(Home, temp);}});router.addRoute( { name: NotFound, path: /404, title:页面不存在,component: NotFound });router.addRoute( { path: /:pathMatch(.*), redirect: /404 });
}5.全局路由守卫中鉴权及激活动态路由
注意在vue-router4.X中动态路由主要通过两个函数实现。router.addRoute() 和 router.removeRoute()。它们只注册一个新的路由也就是说如果新增加的路由与当前位置相匹配就需要你用 router.push() 或 router.replace() 来手动导航才能显示该新路由。
也就是说以前的rouer.addRoutes()添加即可使用动态路由的方式不行了
// 路由守卫鉴权处理
router.beforeEach(async (to, from, next) {let token sessionStorage.getItem(token);let isToken !!token;let loginUser Store.state.user.user;if (isToken) {if (loginUser) {// 如果是login且已经登录了直接跳转到home页面if (to.name Login) return next();// 已经设置过动态路由直接放行没有则需要通过手动调用 router.replace()进行路由显示if (isDynamic) {next();} else {await initDynamicRoutes();isDynamic true;next({ ...to, replace: true });}} else {sessionStorage.clear();next(/login);}} else {isDynamic false;next();}
});
6.第二种方法激活动态路由——在Login.vue和App.vue中调用 这种方式不会每次路由都调用一次添加动态路由方法个人觉得这种方式性能比较好
//App.vue
import { initDynamicRoutes } from /route/route
export default {name: App,created(){initDynamicRoutes();}
}
/scri
//Login.vuetry {await this.$store.dispatch(user/login, {...this.user});//登录成功后根据用户的rights动态添加路由initDynamicRoutes();this.$router.push({ name: Home });} catch (e) {}
7.注意点
7.1 必须使用router.addRoute()方法进行添加动态路由
添加动态路由方法中是使用router.addRoute()方法进行添加Home表示将路由嵌套在Home页面下
rightsList.length 0 rightsList.forEach(item {if (item.path) {const temp routeMapping[item.path];router.addRoute(Home, temp);}});
我试过之前的添加方法已经不能成功添加动态路由了
const currentRoutes router.options.routes;rightsList.length 0 rightsList.forEach(item {if (item.path) {const temp routeMapping[item.path];currentRoutes[1].children.push(temp);}});
7.2 错误页面添加时机
错误页面必须也使用动态添加方法并且在路由动态添加完成后再添加否则如果在基础路由中定义错误页面那么每次点击路由都会首先找路由没找到就会匹配到错误页面从而跳转到错误页面
rightsList.length 0 rightsList.forEach(item {if (item.path) {const temp routeMapping[item.path];router.addRoute(Home, temp);// currentRoutes[1].children.push(temp);}});router.addRoute( { name: NotFound, path: /404, title:页面不存在,component: NotFound });router.addRoute( { path: /:pathMatch(.*), redirect: /404 });
7.3判断动态路由是否启用的标识
如果直接next()会找不到动态路由而直接next({ ...to, replace: true });会导致永远去找动态路由
使用标识后如果有动态路由就加载动态路由没有直接放行
if (isToken) {if (loginUser) {// 如果是login且已经登录了直接跳转到home页面if (to.name Login) return next();// 已经设置过动态路由直接放行没有则需要通过手动调用 router.replace()进行路由显示if (isDynamic) {next();} else {// await initDynamicRoutes();isDynamic true;next({ ...to, replace: true });}} else {sessionStorage.clear();next(/login);}} else {isDynamic false;next();}
7.4警告[Vue Router warn]: No match found for location with path /generateCronjob
以7.2的方式在动态添加完其他路由后再添加错误页面就能成功导到不同路由页面但是警告依然会存在