您好,登錄后才能下訂單哦!
本文小編為大家詳細(xì)介紹“Vue router動(dòng)態(tài)路由如何實(shí)現(xiàn)”,內(nèi)容詳細(xì),步驟清晰,細(xì)節(jié)處理妥當(dāng),希望這篇“Vue router動(dòng)態(tài)路由如何實(shí)現(xiàn)”文章能幫助大家解決疑惑,下面跟著小編的思路慢慢深入,一起來學(xué)習(xí)新知識(shí)吧。
思路其實(shí)很簡單,也很明確:
1、將路由分為靜態(tài)路由(staticRouters)、動(dòng)態(tài)路由
2、靜態(tài)路由初始化時(shí)正常加載
3、用戶登陸后,獲取相關(guān)動(dòng)態(tài)路由數(shù)據(jù),
4、然后利用vue:addRoute追加到vue實(shí)例中即可。 實(shí)現(xiàn)思路雖然很簡單,但是過程并不是一帆風(fēng)順,需要注意的細(xì)節(jié)還是很多的
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) // 解決重復(fù)點(diǎn)擊路由報(bào)錯(cuò)的BUG const originalPush = VueRouter.prototype.push VueRouter.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'), }, ] }, ] // 定義靜態(tài)路由集合 const staticRouterMap = [ 'home', 'lists', 'detail' ] const router = new VueRouter({ mode: 'history', base: process.env.BASE_URL, routes, }) // 路由全局?jǐn)r截 // 以下可根據(jù)業(yè)務(wù)邏輯自行在攔截路由中進(jìn)行處理,此處僅以本人業(yè)務(wù)作為示例展示 // 本示例以 vuex+sessionStorage相互配合完成動(dòng)態(tài)路由的數(shù)據(jù)存儲(chǔ) // 僅以vuex存儲(chǔ)獲取到的動(dòng)態(tài)路由信息后,在刷新頁面時(shí),動(dòng)態(tài)路由信息是會(huì)丟失, // 從而導(dǎo)致頁面404 router.beforeEach((to, from, next) => { const userState = JSON.parse(sessionStorage.getItem('userState')) if (!userState || !userState.isLogin) { // 沒有登錄 // 如果前往頁面非公共路由,則跳轉(zhuǎn)至首頁 if (staticRouterMap.indexOf(to.name) < 0) { next({name: 'home'}) } else { next() } } else { // 登錄 // 已經(jīng)存在路由列表: 注意剛登陸成功第一次調(diào)轉(zhuǎn)route時(shí)相應(yīng)store數(shù)據(jù)還未更新 const hasGetRoute = store.getters['user/hasGetRoute'] const routeMap = JSON.parse(sessionStorage.getItem('routeMap')) if(!hasGetRoute && routeMap) { // 刷新頁面且有route記錄數(shù)據(jù),可再次追加動(dòng)態(tài)路由 store.dispatch('user/updateRouteOfUser', routeMap) next({...to, replace: true}) } else { next() } } }) export default router
view數(shù)據(jù)處理
<template> <div class="home"> <div> 這是demo </div> <div> <div v-show="!isLogin"> <a-divider>調(diào)用接口: 模擬登陸</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 /src import { 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() //以下就是根據(jù)用戶登陸信息,獲取動(dòng)態(tài)路由信息操作 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: { // 用戶狀態(tài)相關(guān) userState: JSON.parse(sessionStorage.getItem('userState')) || {ut: '', isLogin: false, userType: null}, // 用戶信息相關(guān) 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 // 為了防止用戶刷新頁面導(dǎo)致動(dòng)態(tài)創(chuàng)建的路由失效,將其存儲(chǔ)在本地中 sessionStorage.setItem('routeMap', JSON.stringify(routers)); }, setDynamicRouteMap(state, routers) { state.hasGetRoute = true let routerMaps = filterRouter(routers) // 最后追加404路由 routerMaps.push({ path: '*', component: NotFound }) // 追加路由 // 這塊是重點(diǎn),如果直接使用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) }) }, // 獲取用戶授權(quán)動(dòng)態(tài)路由 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 views const loadView = (viewPath) => { return () => import('@/views/' + viewPath) } // Handle routers const filterRouter = (routers) => { return routers.filter((router) => { // 區(qū)分布局與視圖文件,因?yàn)榧虞d方式不同 if (router.component === 'Layout') { router.component = Layout }else { // view router.component = loadView(router.component) } // 刪除路由記錄中的無用字段:這段是本示例與后臺(tái)協(xié)商的,但在vue-router中不被支持的字段信息,可忽略 if (!router.redirect || !router.redirect.length) { delete router.redirect } // 判斷是否存在子路由,并遞歸調(diào)用自己 if(router.children && router.children.length) { router.children = filterRouter(router.children) } return true }) } // mock 數(shù)據(jù) 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;
{ "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動(dòng)態(tài)路由如何實(shí)現(xiàn)”文章已經(jīng)介紹完畢,想要掌握這篇文章的知識(shí)點(diǎn)還需要大家自己動(dòng)手實(shí)踐使用過才能領(lǐng)會(huì),如果想了解更多相關(guān)內(nèi)容的文章,歡迎關(guān)注億速云行業(yè)資訊頻道。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。