两种vue路由
前端路由
- 在router/index.js中直接一次性把所有的路由规则写好,由前端自己定义路由规则,如果有些路由需要根据角色或权限才能展示,可以使用
router.beforeEach((to,from,next)=>{})
前置导航守卫中,根据用户的角色或权限动态展示;如下图:
import Vue from 'vue'
import VueRouter from 'vue-router'
import Login from '@/components/MyLogin.vue'
import Home from '@/components/MyHome.vue'
import MyUsers from '@/components/menus/MyUsers.vue'
import MyRights from '@/components/menus/MyRights.vue'
import MyGoods from '@/components/menus/MyGoods.vue'
import MyOrders from '@/components/menus/MyOrders.vue'
import MySettings from '@/components/menus/MySettings.vue'
import MyUserDetail from '@/components/user/MyUserDetail.vue'
Vue.use(VueRouter)
const router=new VueRouter({
routes:[
{
path:'/',redirect:'/login'
},
{path:'/login',component:Login},
// 嵌套子路由的children属性是一个数组,并且子路由中的path不要带/
{path:'/home',component:Home,
redirect:'/home/myusers',
children:[
// path为空,这是一个默认子路由
{path:'myusers',component:MyUsers},
{path:'myrights',component:MyRights},
{path:'mygoods',component:MyGoods},
{path:'myorders',component:MyOrders},
{path:'mysettings',component:MySettings},
{path:'userdetails/:id',component:MyUserDetail,props:true}
]},
]
})
router.beforeEach((to,from,next)=>{
let pathArr=['/home','/home/myusers','/home/myrights','/home/mygoods','/home/myorders','/home/mysettings']
if(pathArr.indexOf(to.path)!=-1){
const token=localStorage.getItem('token')
if(token)
{
next()
}
else{
next('/login')
}
}else{
next()
}
})
export default router
权限控制的路由
- 当登录后,前端需要根据用户的角色动态地展示路由,因此前端需要发请求调接口拿到后台相对应角色的路由表,并且拿到之后这个路由表需要做一些处理
用户不用登录也会有一些路由可以访问,这些路由成为静态路由;我们在data.js
里放两个数组,分别存放静态路由和动态路由
// 按需导出一个静态路由数组
export const staticRouter= [
{
path:'/',
component:()=>import('../views/1.vue'),
meta:{
title:'1'
}
},
{
path:'/2',
component:()=>import('../views/2.vue'),
meta:{
title:'2'
}
},
{
path:'/3',
component:()=>import('../views/3.vue'),
meta:{
title:'3'
}
},
{
path:'*',
redirect: '/',
meta:{
title:'错误'
}
}
]
// 动态路由,后台返回回来的
export const dynamicRouter=[
{
path:'/4',
component:'4.vue',
meta:{
title:'4'
}
},
{
path:'/5',
component:'5.vue',
meta:{
title:'5'
}
},
{
path:'/6',
component:'6.vue',
meta:{
title:'6'
}
}
]
views/
目录下存放路由组件
同时,需要vuex容器来缓存用户登录的状态和路由表,进行缓存主要是当用户登录后,token值会在一定的时间内有效,也就是这段时间内,用户还是处于登录状态的,那么用户还可以访问哪些权限的路由,当然,如果刷新页面后,会发现vuex容器里面的数据会重置,这时候可以考虑使用本地存储来进行持久化
store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
// 用户是否登录
is:false,
// 存放路由:静态路由+动态路由
routerArr:[]
},
getters: {
updateUser(){
return state.is
},
updateRouter(){
return state.routerArr
}
},
mutations: {
// 点击登录退出
SET_USER(state,value){
state.is=value
},
// 存放路由
SET_ROUTER(state,value){
state.routerArr=value
}
},
actions: {
updateUserChange(context,value){
context.commit('SET_USER',value)
},
updateRouterChange(context,value){
context.commit('SET_ROUTER',value)
}
},
modules: {
}
})
在handleRouter.js
中对路由进行处理,处理的思路是:如果用户没登陆,将静态路由进行缓存到容器,用户登录了,将动态路由进行处理后合并到静态数组里,然后使用router.addRoute()
添加路由,会去掉重复的路由
import { staticRouter,dynamicRouter } from "./data";
import router from "@/router";
import store from "@/store";
const routes=staticRouter
export default function useaddRoute(){
try {
// 如果store有数据-登录
if(store.state.is&&store.state.routerArr.length==4)
{
// 模拟一个异步请求
setTimeout(()=>{
// 把动态路由经过这个函数处理后,push进去,然后返回总的路由表
let allRouter=routesData(dynamicRouter)
// 将路由放进缓存
store.dispatch('updateRouterChange',allRouter)
// 将总的路由表添加到router中
allRouter.forEach(item=>{
router.addRoute(item)
})
},2000)
}else{
// 没有登录,把静态路由放进缓存
store.dispatch('updateRouterChange',staticRouter)
}
} catch (error) {
console.log(error)
}
}
function routesData(result){
result.forEach(item => {
routes.push({
path:item.path,
component:()=>import(`../views/${item.component}`),
meta:item.meta,
}
)
});
return routes
}
App.vue
为什么要在组件的生命周期中create()方法里调用useaddRoute?
假设用户没登陆,组件的生命周期中create()方法里,调用了useaddRoute函数,这个函数执行后,会把静态路由缓存到store中,然后读取store中的路由数组;
假设用户一进页面处于登录状态,组件的生命周期中create()方法里,还是会调用了useaddRoute函数,把静态路由和动态路由都缓存到store的路由数组中;
<template>
<div id="app">
<div v-for="(item, index) in arr" :key="index">
<div>
<router-link :to="item.path">{{ item.meta.title }}</router-link>
</div>
</div>
<button @click="login">登录</button>
<button @click="logout">退出</button>
<router-view></router-view>
</div>
</template>
<script>
import useaddRoute from "./utils/loadingRouter";
export default {
data() {
return {
arr: []
};
},
created() {
useaddRoute();
// this.arr = this.$store.getters.updateRouter;
this.arr = this.$store.state.routerArr;
},
methods: {
async login() {
await this.$store.commit("SET_USER", true);
let isLogin = this.$store.state.is;
isLogin ? useaddRoute() : "";
},
async logout() {
await this.$store.commit("SET_USER", false);
let isLogin = this.$store.state.is;
//退出登录,刷新页面使store容器重置
isLogin ? "" : location.reload();
}
}
};
</script>
<style lang="less" scoped>
</style>
这里模拟后台返回的路由表中,没有涉及到子路由,因为还不太懂,先拿一级路由试试水,以后学到了子路由再说