本文小编为大家详细介绍“Vue router动态路由如何实现”,内容详细,步骤清晰,细节处理妥当,希望这篇“Vue router动态路由如何实现”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。
实现思路
思路其实很简单,也很明确:
将路由分为静态路由(staticRouters)、动态路由
静态路由初始化时正常加载
用户登陆后,获取相关动态路由数据,
然后利用vue:addRoute追加到vue实例中即可。 实现思路虽然很简单,但是过程并不是一帆风顺,需要注意的细节还是很多的
环境介绍
vue-cli: v4.x.x
vue: v2.6.11
vuex: v3.4.0
vue-router: v3.2.0
实现过程
路由文件处理(router/index.js):
import Vue from 'vue'import VueRouter from 'vue-router'import HomeLayout from '../layouts/HomeLayout'import store from '@/store/index'Vue.use(VueRouter)// 解决重复点击路由报错的BUGconst originalPush = VueRouter.prototype.pushVueRouter.prototype.push = function push(location) { return originalPush.call(this, location).catch((err) => err)}const routes = [{path: '/',name: 'homeBase',component: HomeLayout,redirect: {name: 'home'},children: [// 门户路由{path: 'home',name: 'home',component: () => import('../views/portal/Home.vue'),},{path: 'lists',name: 'lists',component: () => import('../views/portal/Lists.vue'),},{path: 'detail',name: 'detail',component: () => import('../views/portal/Detail.vue'),},]},]// 定义静态路由集合const staticRouterMap = ['home','lists','detail']const router = new VueRouter({mode: 'history',base: process.env.BASE_URL,routes,})// 路由全局拦截// 以下可根据业务逻辑自行在拦截路由中进行处理,此处仅以本人业务作为示例展示// 本示例以 vuex+sessionStorage相互配合完成动态路由的数据存储// 仅以vuex存储获取到的动态路由信息后,在刷新页面时,动态路由信息是会丢失,// 从而导致页面404router.beforeEach((to, from, next) => {const userState = JSON.parse(sessionStorage.getItem('userState'))if (!userState || !userState.isLogin) {// 没有登录// 如果前往页面非公共路由,则跳转至首页if (staticRouterMap.indexOf(to.name) < 0) {next({name: 'home'})} else {next()}} else {// 登录// 已经存在路由列表: 注意刚登陆成功第一次调转route时相应store数据还未更新const hasGetRoute = store.getters['user/hasGetRoute']const routeMap = JSON.parse(sessionStorage.getItem('routeMap'))if(!hasGetRoute && routeMap) { // 刷新页面且有route记录数据,可再次追加动态路由store.dispatch('user/updateRouteOfUser', routeMap)next({...to, replace: true})} else {next()}}})export default router
view数据处理
<template><div class="home"><div>这是demo</div><div><div v-show="!isLogin"><a-divider>调用接口: 模拟登陆</a-divider><div ><a-space :size="size"><a-button type="primary" @click="login()">用户登陆</a-button></a-space><p>{{loading}}</p></div></div></div></div></template><script>// @ is an alias to /srcimport {Base64} from 'js-base64'import User from '../../api/user'import {mapGetters,mapMutations,mapActions} from 'vuex'export default {name: 'home',data() {return {size: "middle",user: {'name': 'xxxx','pass': Base64.encode('xxxx')},}},components: {},computed: {...mapGetters('user', ['isLogin', 'userInfo', 'hasGetRoute'])},methods: {...mapMutations('user', ['setUserState']),...mapActions('user', ['getUserInfo', 'getDynamicRouteOfUser']),login() {if (this.isLogin) {this.$router.push({path: '/user'})} else {// 模拟用户User.login(this.user).then(res => {this.setUserState({'isLogin': true,'ut': res.data.user_token,'userType': 1})this.getUserInfo()//以下就是根据用户登陆信息,获取动态路由信息操作this.getDynamicRouteOfUser(type).then(() => {this.$router.push({path: '/user'})})}).catch(() => {})}},},}</script><style lang="scss" scoped>.home {padding: 20px;}</style>
vuex
import VueRouter from '../../router'import UserApi from '../../api/user'import axios from 'axios'import TeacherLayout from '@/layouts/Layout'import NotFound from '@/layouts/404'const user = { namespaced: true, state: { // 用户状态相关 userState: JSON.parse(sessionStorage.getItem('userState')) || {ut: '', isLogin: false, userType: null}, // 用户信息相关 userInfo: JSON.parse(sessionStorage.getItem('userInfo')) || {}, // 是否获取route hasGetRoute: false, // routeMap routeMap: JSON.parse(sessionStorage.getItem('routeMap')) || [], }, getters: { ut : state => state.userState.ut, isLogin: state => !!state.userState.isLogin, userInfo: state => state.userInfo, hasGetRoute: state => state.hasGetRoute, routeMap: state => state.routeMap[0].children, }, mutations: { setUserState(state, playload) { state.userState = playload sessionStorage.setItem('userState', JSON.stringify(state.userState)) }, setUserInfo(state, playload) { state.userInfo = playload sessionStorage.setItem('userInfo', JSON.stringify(state.userInfo)) }, setRouteMap(state, routers) { state.routeMap = routers // 为了防止用户刷新页面导致动态创建的路由失效,将其存储在本地中 sessionStorage.setItem('routeMap', JSON.stringify(routers)); }, setDynamicRouteMap(state, routers) { state.hasGetRoute = true let routerMaps = filterRouter(routers) // 最后追加404路由 routerMaps.push({ path: '*', component: NotFound }) // 追加路由 // 这块是重点,如果直接使用addRoute是无效的 routerMaps.forEach(item => { VueRouter.addRoute(item); }) }, resetLogin() { sessionStorage.clear() } }, actions: { // 获取用户信息 async getUserInfo({commit}) { await UserApi.user().then(res => { commit('setUserInfo', res) }).catch(error => { console.log(error) }) }, // 获取用户授权动态路由 async getDynamicRouteOfUser({commit}, type) { let flag = false // mock api mockRouter().then(res => { commit('setRouteMap', res.data) commit('setDynamicRouteMap', res.data) flag = true }).catch(err => { console.log(err) }) return flag }, // 刷新重置路由 updateRouteOfUser({commit}, routerMap) { commit('setDynamicRouteMap', routerMap) }, }}// handle viewsconst loadView = (viewPath) => { return () => import('@/views/' + viewPath)}// Handle routersconst filterRouter = (routers) => { return routers.filter((router) => { // 区分布局与视图文件,因为加载方式不同 if (router.component === 'Layout') { router.component = Layout }else { // view router.component = loadView(router.component) } // 删除路由记录中的无用字段:这段是本示例与后台协商的,但在vue-router中不被支持的字段信息,可忽略 if (!router.redirect || !router.redirect.length) { delete router.redirect } // 判断是否存在子路由,并递归调用自己 if(router.children && router.children.length) { router.children = filterRouter(router.children) } return true })} // mock 数据async function mockRouter() { const url = 'http://localhost:8080/t.json' let routerData await axios.get(url).then(res => { routerData = res.data }).catch(err => { console.log(err) }) return routerData}export default user;
路由数据(demo)
{ "data":[ { "title":"demo", "name":"x", "pname":"", "path": "/x", "type": 1, "component": "Layout", "redirect": {"name": "xx"}, "children": [ { "title":"child1", "name":"xx", "pname":"x", "path": "", "type": 2, "icon": "desktop", "component": "xx.vue", "redirect": {} }, { "title":"child1", "name":"xx", "pname":"tBase", "path": "xx", "type": 2, "icon": "container", "component": "xx.vue", "redirect": {"name": "xxx"}, "children": [ { "title":"child2", "name":"xx", "pname":"xx", "path": "xx", "type": 2, "icon": "unordered-list", "component": "xx.vue", "redirect": {} } ] }, ] } ]}
读到这里,这篇“Vue router动态路由如何实现”文章已经介绍完毕,想要掌握这篇文章的知识点还需要大家自己动手实践使用过才能领会,如果想了解更多相关内容的文章,欢迎关注编程网行业资讯频道。