VueRouter實(shí)現(xiàn)動(dòng)態(tài)路由的示例分析-創(chuàng)新互聯(lián)

這篇文章主要介紹Vue Router實(shí)現(xiàn)動(dòng)態(tài)路由的示例分析,文中介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們一定要看完!

我們一直強(qiáng)調(diào)網(wǎng)站設(shè)計(jì)、成都網(wǎng)站建設(shè)對(duì)于企業(yè)的重要性,如果您也覺得重要,那么就需要我們慎重對(duì)待,選擇一個(gè)安全靠譜的網(wǎng)站建設(shè)公司,企業(yè)網(wǎng)站我們建議是要么不做,要么就做好,讓網(wǎng)站能真正成為企業(yè)發(fā)展過程中的有力推手。專業(yè)網(wǎng)絡(luò)公司不一定是大公司,成都創(chuàng)新互聯(lián)公司作為專業(yè)的網(wǎng)絡(luò)公司選擇我們就是放心。

個(gè)人理解:動(dòng)態(tài)路由不同于常見的靜態(tài)路由,可以根據(jù)不同的「因素」而改變站點(diǎn)路由列表。常見的動(dòng)態(tài)路由大都是用來實(shí)現(xiàn):多用戶權(quán)限系統(tǒng)不同用戶展示不同導(dǎo)航菜單。

如何利用Vue Router 實(shí)現(xiàn)動(dòng)態(tài)路由

Vue項(xiàng)目實(shí)現(xiàn)動(dòng)態(tài)路由的方式大體可分為兩種:

  • 前端將全部路由規(guī)定好,登錄時(shí)根據(jù)用戶角色權(quán)限來動(dòng)態(tài)展示路由;

  • 路由存儲(chǔ)在數(shù)據(jù)庫中,前端通過接口獲取當(dāng)前用戶對(duì)應(yīng)路由列表并進(jìn)行渲染;

第一種方式在很多Vue UI Admin上都實(shí)現(xiàn)了,可以去讀一下他們的源碼理解具體的實(shí)現(xiàn)思路,這里就不過多展開。第二種方式現(xiàn)在來說也比較常見了,因?yàn)榻陧?xiàng)目正好用到所以單獨(dú)講一下,這里我使用的方案是利用Vue Router的一些特性實(shí)現(xiàn)后端主導(dǎo)的動(dòng)態(tài)路由。

使用到的功能特性

Vue Router 全局前置守衛(wèi)

官網(wǎng)解釋

這里我們主要借助全局前置守衛(wèi)的「前置」特性,在頁面加載前將當(dāng)前用戶所用到的路由列表注入到Router實(shí)例中,注入使用到的方法則是下面的router.addRoutes方法。

Vue Router router.addRoutes 實(shí)例方法

官網(wǎng)解釋

router.addRoutes方法可以為Router實(shí)例動(dòng)態(tài)添加路由規(guī)則,剛好為我們實(shí)現(xiàn)動(dòng)態(tài)路由提供了注入方法。

Vue Router 路由懶加載

官網(wǎng)解釋

懶加載這個(gè)功能不是動(dòng)態(tài)路由的必要功能,但既然提供了這一特性,所以就直接在項(xiàng)目中使用了。

具體思路

基礎(chǔ)信息準(zhǔn)備

前端代碼實(shí)現(xiàn)基本靜態(tài)路由,例如:登錄頁路由,服務(wù)器錯(cuò)誤頁路由等(這里有一個(gè)坑,后面講)。數(shù)據(jù)庫存儲(chǔ)全部動(dòng)態(tài)路由信息。

數(shù)據(jù)庫如何存儲(chǔ)動(dòng)態(tài)路由信息?我選擇的方案是現(xiàn)將路由引用的對(duì)象字符串化,再將路由列表轉(zhuǎn)化為JSON格式傳輸給后端,經(jīng)后端處理后存儲(chǔ)到數(shù)據(jù)庫里??傊谇昂蠖诉M(jìn)行傳遞的是JSON格式的路由列表信息。

如何將路由中引用的對(duì)象字符串化?我遇到的實(shí)際問題是:使用的UI組件提供了布局方案,需要引用布局組件并在子路由處引用具體頁面。我選擇的解決方案是:區(qū)別對(duì)待需要引用布局組件的component屬性,使用簡(jiǎn)短字符串代替布局組件,使用文件路徑字符串代替頁面引入。具體實(shí)現(xiàn)可以看后面的代碼實(shí)例。

利用全局前置守衛(wèi)對(duì)路由信息進(jìn)行判斷

1-判斷用戶是否登錄1.1-若未登錄,跳轉(zhuǎn)至登錄頁面1.2-若已經(jīng)登錄,判斷是否已獲取路由列表1.2.1-若未獲取,從后端獲取、解析并保存到Vuex中1.2.2-若已獲取,跳轉(zhuǎn)至目標(biāo)頁面

這里我沒做太多考察,直接將取到數(shù)據(jù)存儲(chǔ)到了Vuex中,在實(shí)際項(xiàng)目應(yīng)用的過程中應(yīng)考慮數(shù)據(jù)存儲(chǔ)的安全性。

如何實(shí)現(xiàn)路由列表解析?

  1. JSON格式的路由信息解析為JavaScript列表對(duì)象;

  2. 利用列表對(duì)象的filter方法實(shí)現(xiàn)解析函數(shù),通過component判斷是否為布局組件;

  3. 若為布局組件,使用布局組件代替component字符串;

  4. 若為具體頁面,使用loadView函數(shù)加載對(duì)應(yīng)的具體頁面;

  5. 利用 router.addRoutes 方法動(dòng)態(tài)添加路由

這一步就很簡(jiǎn)單了,將解析好的路由列表通過router.addRoutes方法添加到Router實(shí)例中即可。

簡(jiǎn)單的實(shí)現(xiàn)代碼

// router/index.js
import Vue from 'vue'
import store from '@/store'
import Router from 'vue-router'
import { getToken } from '@/lib/util'

Vue.use(Router)

// 定義靜態(tài)路由
const staticRoutes = [
 {
 path: '/login',
 name: 'login',
 meta: {
 title: '登錄頁面',
 hideInMenu: true
 },
 component: () => import('@/view/login/login.vue')
 },
 {
 path: '/401',
 name: 'error_401',
 meta: {
 hideInMenu: true
 },
 component: () => import('@/view/error-page/401.vue')
 },
 {
 path: '/500',
 name: 'error_500',
 meta: {
 hideInMenu: true
 },
 component: () => import('@/view/error-page/500.vue')
 }
]

// 定義登錄頁面名稱(為了方便理解才定義的)
const LOGIN_PAGE_NAME = 'login'

// 實(shí)例化 Router 對(duì)象
const router = new Router({
 staticRoutes,
 mode: 'history'
})

// 定義全局前置守衛(wèi)(里面有兩個(gè)坑要注意)
router.beforeEach((to, from, next) => {
 // 通過自定義方法獲取用戶 token 用來判斷用戶登錄狀態(tài)
 const token = getToken()
 if (!token && to.name !== LOGIN_PAGE_NAME) {
 // 如果沒有登錄而且前往的頁面不是登錄頁面,跳轉(zhuǎn)到登錄頁
 next({ name: LOGIN_PAGE_NAME })
 } else if (!token && to.name === LOGIN_PAGE_NAME) {
 // 如果沒有登錄而且前往的頁面是登錄頁面,跳轉(zhuǎn)到登錄頁面
 // 這里有一個(gè)坑,一定要注意這一步和上一步得分開寫
 // 如果把前兩步判斷合并為 if (!token) next({ name:login })
 // 則會(huì)形成登錄頁面無限刷新的錯(cuò)誤,具體成因后面解釋
 next()
 } else {
 // 如果登錄了
 if (!store.state.app.hasGetRoute) {
 // 如果沒有獲取路由信息,先獲取路由信息而后跳轉(zhuǎn)
 store.dispatch('getRouteList').then(() => {
 router.addRoutes(store.state.app.routeList)
 // 這里也是一個(gè)坑,不能使用簡(jiǎn)單的 next()
 // 如果直接使用 next() 刷新后會(huì)一直白屏
 next({ ...to, replace: true })
 })
 } else {
 // 如果已經(jīng)獲取路由信息,直接跳轉(zhuǎn)
 next()
 }
 }
})

export default router
// store/index.js
import router from '@/router'
import Main from '@/components/main'
import { getToken } from '@/lib/util'
import { getRoute } from '@/api/app'

const loadView = (viewPath) => {
 // 用字符串模板實(shí)現(xiàn)動(dòng)態(tài) import 從而實(shí)現(xiàn)路由懶加載
 return () => import(`@/view/${viewPath}`)
}

const filterAsyncRouter = (routeList) => {
 return routeList.map((route) => {
 if (route.component) {
 if (route.component === 'Main') {
 // 如果 component = Main 說明是布局組件
 // 將真正的布局組件賦值給它
 route.component = Main
 } else {
 // 如果不是布局組件就只能是頁面的引用了
 // 利用懶加載函數(shù)將實(shí)際頁面賦值給它
 route.component = loadView(route.component)
 }
 // 判斷是否存在子路由,并遞歸調(diào)用自己
 if (route.children && route.children.length) {
 route.children = filterAsyncRouter(route.children)
 }
 }
 })
}

export default {
 state: {
 routeList: [],
 token: getToken(),
 hasGetRoute: false
 },
 mutations: {
 setRouteList(state, data) {
 // 先將 JSON 格式的路由列表解析為 JavaScript List
 // 再用路由解析函數(shù)解析 List 為真正的路由列表
 state.routeList = filterAsyncRouter(JSON.parse(data))
 // 修改路由獲取狀態(tài)
 state.hasGetRoute = true
 }
 },
 atcions: {
 getRouteList({ state, commit }) {
 return new Promise((resolve) => {
 const token = state.token
 getRoute({ token }).then((res) => {
 let data = res.data.data
 // 注意這里取出的是 JSON 格式的路由列表
 commit('setRouteList', data)
 resolve()
 })
 })
 }
 }
}

常見問題

頁面卡在登錄頁面而且不斷刷新

這個(gè)問題的解決方案在「實(shí)現(xiàn)代碼」中已經(jīng)提到了,只需要在判斷登錄狀態(tài)的時(shí)候注意不要將兩種未登錄狀態(tài)混為一談即可。但這樣治標(biāo)不治本,因?yàn)橥瑯拥膯栴}可以由不同形式的代碼導(dǎo)致,那導(dǎo)致問題的原因是什么那?然我們慢慢分析:

我們先假設(shè)不小心把兩種未登錄的狀態(tài)混在一起判斷:

if (!token) {
 next({ name: LOGIN_PAGE_NAME })
}

這里的next({ name: LOGIN_PAGE_NAME })方法會(huì)再一次激活全局前置守衛(wèi),從而導(dǎo)致再一次進(jìn)入判斷并觸發(fā)next({ name: LOGIN_PAGE_NAME }),如此遞歸調(diào)用下去,頁面就會(huì)卡主并且不斷刷新。

動(dòng)態(tài)路由配合路由懶加載

實(shí)現(xiàn)這一目的的方案也在代碼示例中展示了:

const loadView = (viewPath) => {
 return () => import(`@/view/${viewPath}`)
}

這里是運(yùn)用了一個(gè) JavaScript 不太常用的特性:字符串模板,使用此特性讓不支持字符串拼接的import操作能夠?qū)崿F(xiàn)動(dòng)態(tài)import不同的模塊。

動(dòng)態(tài)路由刷新后 404

這應(yīng)該是本方案中最常見的一個(gè)錯(cuò)誤之一,其原意是很多人在創(chuàng)建「基本靜態(tài)路由」的時(shí)候回把 404 頁面的路由也加入在里面,從而導(dǎo)致頁面加載初期動(dòng)態(tài)路由還沒有加入到路由實(shí)例中,匹配范圍最廣的 404 頁面就會(huì)跳出來。解決方法就是將 404 頁面的路由也加入到動(dòng)態(tài)路由中。

動(dòng)態(tài)路由刷新后變空白頁

造成這一問題的原因有很多,我這里遇到的問題是使用參考文章3解決的,但具體原理我還沒弄清楚,等我做一下研究再來更新。

動(dòng)態(tài)路由頁面刷新時(shí) Title 不穩(wěn)定

造成這一問題的原因很簡(jiǎn)單:因?yàn)轫撁嫠⑿碌臅r(shí)候路由信息還沒加載進(jìn)來,所以根本沒有標(biāo)題信息可供加載。但是我還沒找到比較好的解決方案,同樣等我研究一下再更新。

以上是“Vue Router實(shí)現(xiàn)動(dòng)態(tài)路由的示例分析”這篇文章的所有內(nèi)容,感謝各位的閱讀!希望分享的內(nèi)容對(duì)大家有幫助,更多相關(guān)知識(shí),歡迎關(guān)注創(chuàng)新互聯(lián)成都網(wǎng)站設(shè)計(jì)公司行業(yè)資訊頻道!

另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)scvps.cn,海內(nèi)外云服務(wù)器15元起步,三天無理由+7*72小時(shí)售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國(guó)服務(wù)器、虛擬主機(jī)、免備案服務(wù)器”等云主機(jī)租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡(jiǎn)單易用、服務(wù)可用性高、性價(jià)比高”等特點(diǎn)與優(yōu)勢(shì),專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場(chǎng)景需求。

網(wǎng)頁題目:VueRouter實(shí)現(xiàn)動(dòng)態(tài)路由的示例分析-創(chuàng)新互聯(lián)
鏈接地址:http://muchs.cn/article30/djicpo.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供響應(yīng)式網(wǎng)站、品牌網(wǎng)站設(shè)計(jì)靜態(tài)網(wǎng)站、微信小程序建站公司、App設(shè)計(jì)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

外貿(mào)網(wǎng)站制作