成人在线亚洲_国产日韩视频一区二区三区_久久久国产精品_99国内精品久久久久久久

您的位置:首頁技術文章
文章詳情頁

Vue Router 實現動態路由和常見問題及解決方法

瀏覽:148日期:2023-02-03 08:13:24

個人理解:動態路由不同于常見的靜態路由,可以根據不同的「因素」而改變站點路由列表。常見的動態路由大都是用來實現:多用戶權限系統不同用戶展示不同導航菜單。

如何利用Vue Router 實現動態路由

Vue項目實現動態路由的方式大體可分為兩種:

前端將全部路由規定好,登錄時根據用戶角色權限來動態展示路由; 路由存儲在數據庫中,前端通過接口獲取當前用戶對應路由列表并進行渲染;

第一種方式在很多Vue UI Admin上都實現了,可以去讀一下他們的源碼理解具體的實現思路,這里就不過多展開。第二種方式現在來說也比較常見了,因為近期項目正好用到所以單獨講一下,這里我使用的方案是利用Vue Router的一些特性實現后端主導的動態路由。

使用到的功能特性

Vue Router 全局前置守衛

官網解釋

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

Vue Router router.addRoutes 實例方法

官網解釋

router.addRoutes方法可以為Router實例動態添加路由規則,剛好為我們實現動態路由提供了注入方法。

Vue Router 路由懶加載

官網解釋

懶加載這個功能不是動態路由的必要功能,但既然提供了這一特性,所以就直接在項目中使用了。

具體思路

基礎信息準備

前端代碼實現基本靜態路由,例如:登錄頁路由,服務器錯誤頁路由等(這里有一個坑,后面講)。數據庫存儲全部動態路由信息。

數據庫如何存儲動態路由信息?我選擇的方案是現將路由引用的對象字符串化,再將路由列表轉化為JSON格式傳輸給后端,經后端處理后存儲到數據庫里。總之在前后端進行傳遞的是JSON格式的路由列表信息。

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

利用全局前置守衛對路由信息進行判斷

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

這里我沒做太多考察,直接將取到數據存儲到了Vuex中,在實際項目應用的過程中應考慮數據存儲的安全性。

如何實現路由列表解析?

將JSON格式的路由信息解析為JavaScript列表對象; 利用列表對象的filter方法實現解析函數,通過component判斷是否為布局組件; 若為布局組件,使用布局組件代替component字符串; 若為具體頁面,使用loadView函數加載對應的具體頁面; 利用 router.addRoutes 方法動態添加路由

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

簡單的實現代碼

// router/index.jsimport Vue from ’vue’import store from ’@/store’import Router from ’vue-router’import { getToken } from ’@/lib/util’Vue.use(Router)// 定義靜態路由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’// 實例化 Router 對象const router = new Router({ staticRoutes, mode: ’history’})// 定義全局前置守衛(里面有兩個坑要注意)router.beforeEach((to, from, next) => { // 通過自定義方法獲取用戶 token 用來判斷用戶登錄狀態 const token = getToken() if (!token && to.name !== LOGIN_PAGE_NAME) { // 如果沒有登錄而且前往的頁面不是登錄頁面,跳轉到登錄頁 next({ name: LOGIN_PAGE_NAME }) } else if (!token && to.name === LOGIN_PAGE_NAME) { // 如果沒有登錄而且前往的頁面是登錄頁面,跳轉到登錄頁面 // 這里有一個坑,一定要注意這一步和上一步得分開寫 // 如果把前兩步判斷合并為 if (!token) next({ name:login }) // 則會形成登錄頁面無限刷新的錯誤,具體成因后面解釋 next() } else { // 如果登錄了 if (!store.state.app.hasGetRoute) { // 如果沒有獲取路由信息,先獲取路由信息而后跳轉 store.dispatch(’getRouteList’).then(() => { router.addRoutes(store.state.app.routeList) // 這里也是一個坑,不能使用簡單的 next() // 如果直接使用 next() 刷新后會一直白屏 next({ ...to, replace: true }) }) } else { // 如果已經獲取路由信息,直接跳轉 next() } }})export default router

// store/index.jsimport router from ’@/router’import Main from ’@/components/main’import { getToken } from ’@/lib/util’import { getRoute } from ’@/api/app’const loadView = (viewPath) => { // 用字符串模板實現動態 import 從而實現路由懶加載 return () => import(`@/view/${viewPath}`)}const filterAsyncRouter = (routeList) => { return routeList.map((route) => { if (route.component) { if (route.component === ’Main’) { // 如果 component = Main 說明是布局組件 // 將真正的布局組件賦值給它 route.component = Main } else { // 如果不是布局組件就只能是頁面的引用了 // 利用懶加載函數將實際頁面賦值給它 route.component = loadView(route.component) } // 判斷是否存在子路由,并遞歸調用自己 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 // 再用路由解析函數解析 List 為真正的路由列表 state.routeList = filterAsyncRouter(JSON.parse(data)) // 修改路由獲取狀態 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() }) }) } }}

常見問題

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

這個問題的解決方案在「實現代碼」中已經提到了,只需要在判斷登錄狀態的時候注意不要將兩種未登錄狀態混為一談即可。但這樣治標不治本,因為同樣的問題可以由不同形式的代碼導致,那導致問題的原因是什么那?然我們慢慢分析:

我們先假設不小心把兩種未登錄的狀態混在一起判斷:

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

這里的next({ name: LOGIN_PAGE_NAME })方法會再一次激活全局前置守衛,從而導致再一次進入判斷并觸發next({ name: LOGIN_PAGE_NAME }),如此遞歸調用下去,頁面就會卡主并且不斷刷新。

動態路由配合路由懶加載

實現這一目的的方案也在代碼示例中展示了:

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

這里是運用了一個 JavaScript 不太常用的特性:字符串模板,使用此特性讓不支持字符串拼接的import操作能夠實現動態import不同的模塊。

動態路由刷新后 404

這應該是本方案中最常見的一個錯誤之一,其原意是很多人在創建「基本靜態路由」的時候回把 404 頁面的路由也加入在里面,從而導致頁面加載初期動態路由還沒有加入到路由實例中,匹配范圍最廣的 404 頁面就會跳出來。解決方法就是將 404 頁面的路由也加入到動態路由中。

動態路由刷新后變空白頁

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

動態路由頁面刷新時 Title 不穩定

造成這一問題的原因很簡單:因為頁面刷新的時候路由信息還沒加載進來,所以根本沒有標題信息可供加載。但是我還沒找到比較好的解決方案,同樣等我研究一下再更新。

參考大師兄:

Vue 動態路由的實現……

Vue Router 文檔頁面

rambo:vue router 動態路由 刷新后變空白頁

總結

到此這篇關于Vue Router 實現動態路由和常見問題及解決方法的文章就介紹到這了,更多相關vue router 動態路由內容請搜索好吧啦網以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持好吧啦網!

標簽: Vue
相關文章:
成人在线亚洲_国产日韩视频一区二区三区_久久久国产精品_99国内精品久久久久久久
日韩精品中午字幕| 亚洲欧美春色| 色一情一乱一乱一91av| 一区二区在线电影| 国产福利电影一区二区三区| 欧美自拍丝袜亚洲| 日韩成人一级片| 亚洲一区视频| 亚洲成人在线免费| 香蕉成人久久| 亚洲午夜久久久| 国产精品视频福利| 亚洲成av人综合在线观看| 午夜在线观看免费一区| 亚洲成人综合网站| 久久成人国产| 三级久久三级久久久| 色综合久久久久久久| 丝袜美腿亚洲一区二区图片| 噜噜噜噜噜久久久久久91| 亚洲精品福利视频网站| 日韩香蕉视频| 亚洲蜜桃精久久久久久久| 国产精品videosex极品| 中文久久乱码一区二区| 国户精品久久久久久久久久久不卡| 国产亚洲自拍一区| 欧美一区综合| 国产欧美日韩在线看| 国内一区二区在线视频观看 | 欧美日韩久久久| 久久99国产精品尤物| 欧美探花视频资源| 国产精品18久久久久久久久| 日韩免费一区二区| 国产高清在线精品| 久久久久久久久蜜桃| 国产精品国产三级欧美二区| 亚洲精品欧美专区| 久久婷婷一区| 国产一区二区三区观看| 日韩免费福利电影在线观看| 91丨九色丨蝌蚪富婆spa| 国产精品久久久久久久久免费桃花 | 99精品国产高清一区二区| 一区二区三区美女视频| 亚洲自拍高清| 国模套图日韩精品一区二区| 日韩欧美国产不卡| 欧美精品18| 亚洲综合一二三区| 欧美午夜一区二区三区| 成人高清视频免费观看| 国产精品久久久久久福利一牛影视 | 欧美久久久久久久| 夜夜揉揉日日人人青青一国产精品| 麻豆91精品| 国产精品69毛片高清亚洲| 国产亚洲欧美日韩日本| 亚洲日本视频| 久久精品国产亚洲高清剧情介绍| 日韩欧美电影一区| 一区二区亚洲精品| 日韩高清一级片| 欧美本精品男人aⅴ天堂| 精品999网站| 免费高清视频精品| 久久亚洲私人国产精品va媚药| 亚洲国产清纯| 精品一区二区三区av| 国产蜜臀97一区二区三区| 亚洲免费网址| 国产69精品久久久久777| 亚洲欧美视频在线观看视频| 欧美日韩中字一区| 欧美xxx在线观看| 日韩在线a电影| 亚洲精品在线免费播放| 亚洲一区在线免费| 国产91对白在线观看九色| 亚洲六月丁香色婷婷综合久久 | 国产成人欧美日韩在线电影| 最新热久久免费视频| 色狠狠色噜噜噜综合网| 91蝌蚪porny| 亚洲国产成人高清精品| 欧美一区二区三区视频免费播放| 国产综合色产| 日本美女视频一区二区| 精品少妇一区二区三区免费观看| 一区二区三区视频在线播放| 国产黄色成人av| 亚洲精品高清视频在线观看| 日韩丝袜情趣美女图片| 亚洲一区欧美激情| 成人18精品视频| 天堂在线一区二区| 中文字幕欧美三区| 欧美精品一二三四| 国产欧美日韩在线播放| 国产成人精品aa毛片| 一区二区三区在线视频观看58| 日韩欧美激情一区| 国产日韩欧美一区在线| 成人中文字幕合集| 视频一区欧美日韩| 国产精品人成在线观看免费| 欧美三级乱人伦电影| 亚洲激情在线| 床上的激情91.| 免费观看成人鲁鲁鲁鲁鲁视频| 亚洲欧美一区二区在线观看| 日韩视频一区在线观看| 久久一区欧美| 亚洲性感美女99在线| 成a人片亚洲日本久久| 麻豆国产精品777777在线| 亚洲欧美日韩一区二区三区在线观看| 欧美一区二区三区视频在线| 久久久久国产精品一区二区| 欧美三级网页| 丰满放荡岳乱妇91ww| 麻豆91精品91久久久的内涵| 亚洲精品国产无套在线观| 国产日产精品1区| 91精品免费在线| 久久亚洲午夜电影| 夜夜爽www精品| 欧美高清一区二区| 国产99久久久久久免费看农村| 免费在线观看日韩欧美| 亚洲国产综合91精品麻豆| 日韩精品一区二区三区在线 | 日本一区二区免费在线观看视频| 欧美日韩一二三| 亚洲免费网站| 伊人久久大香线蕉综合热线| 成人av先锋影音| 国产精品原创巨作av| 天天影视涩香欲综合网| 亚洲色图另类专区| 久久精品一区蜜桃臀影院| 日韩小视频在线观看专区| 欧美在线观看18| 男女精品网站| 一区二区激情| 亚洲精品极品| 亚洲大片av| 国产精品国码视频| 91蜜桃网址入口| 91网站黄www| 成人av一区二区三区| 国产精品一区三区| 国产综合久久久久久鬼色| 日韩精品成人一区二区三区| 亚洲最大的成人av| 亚洲乱码国产乱码精品精小说| 亚洲国产精华液网站w| 国产日产欧美一区二区视频| wwwwww.欧美系列| 26uuu亚洲婷婷狠狠天堂| 欧美变态tickling挠脚心| 日韩精品专区在线影院重磅| 日韩一区二区在线免费观看| 7777精品伊人久久久大香线蕉的| 欧美乱妇23p| 欧美欧美欧美欧美首页| 欧美日本韩国一区| 91精品国产91久久久久久最新毛片 | 欧美一级爆毛片| 69精品人人人人| 欧美一级在线观看| 欧美一卡在线观看| 日韩欧美国产三级| 欧美精品一区二区三区在线| 久久免费电影网| 国产欧美日韩亚州综合| 国产精品欧美久久久久一区二区| 日韩欧美一区二区久久婷婷| 日韩美女一区二区三区| 精品人伦一区二区色婷婷| 久久九九久久九九| 中文字幕av不卡| 亚洲欧美激情一区二区| 一区二区三区精品视频| 午夜久久久久久| 久久精品72免费观看| 国产精品资源在线看| 不卡视频一二三| 国产精品啊v在线| aⅴ色国产欧美| 久久精品国产清高在天天线| 在线看国产日韩| 日韩欧美成人一区| 久久久久久99久久久精品网站| 国产精品三级在线观看| 一区二区三区四区不卡视频| 亚洲成人av中文| 久久99精品久久久久久动态图 | 尹人成人综合网|