欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

詳解Vue3如何加載動態(tài)菜單

 更新時間:2022年07月20日 11:01:57   作者:江南一點雨  
這篇文章主要為大家詳細介紹了Vue3是如何實現(xiàn)加載動態(tài)菜單功能的,文中的示例代碼講解詳細,對我們學習Vue有一定幫助,需要的可以參考一下

1. 整體思路

首先我們來梳理下整體上的實現(xiàn)思路,首先一點:整體思路和 vhr 一模一樣。

考慮到有的小伙伴可能已經忘記 vhr 中前端動態(tài)菜單的實現(xiàn)思路了,因此本文再和大家分析一下。

為了確保在所有的 .vue 文件中都能訪問到到菜單數(shù)據(jù),所以選擇將菜單數(shù)據(jù)存入 vuex 中,vuex 是 vue 中一個存儲數(shù)據(jù)的公共地方,所有的 .vue 文件都可以從 vuex 中讀取到數(shù)據(jù)。存儲在 vuex 中的數(shù)據(jù)本質上是存在內存中,所以它有一個特點,就是瀏覽器按 F5 刷新之后,數(shù)據(jù)就沒了。所以在發(fā)生頁面的跳轉的時候,我們應該去區(qū)分一下,是用戶點擊了頁面上的菜單按鈕之后發(fā)生了頁面跳轉還是用戶點擊了瀏覽器刷新按鈕(或者按了 F5)發(fā)生了跳轉。

為了實現(xiàn)這一點,我們需要用到 vue 中的路由導航守衛(wèi)功能,對于我們 Java 工程師而言,這些可能聽起來有點陌生,但是你把它當作 Java 中的 Filter 來看待就好理解了,實際上我們視頻中和小伙伴們講解的時候就是這么類比的,將一個新事物跟我們腦海中一個已有的熟悉的事物進行類比,就很容易理解了。

vue 中的導航守衛(wèi)就類似一個監(jiān)控,它可以監(jiān)控到所有的頁面跳轉,在頁面跳轉中,我們可以去判斷一下 vuex 中的菜單數(shù)據(jù)是否還在,如果還在,就說明用戶是點擊了頁面上的菜單按鈕完成了跳轉的,如果不在,就說明用戶是點擊了瀏覽器的刷新按鈕或者是按了 F5 進行頁面刷新的,此時我們就要趕緊去服務端重新加載一下菜單數(shù)據(jù)。

---xxxxxxxxxxxxxxxxxx---

整體上的實現(xiàn)思路就是這樣,接下來我們來看看一些具體的實現(xiàn)細節(jié)。

2. 實現(xiàn)細節(jié)

2.1 加載細節(jié)

首先我們來看看加載的細節(jié)。

小伙伴們知道,單頁面項目的入口是 main.js,路由加載的內容在 src/permission.js 文件中,該文件在 main.js 中被引入,src/permission.js 中的前置導航守衛(wèi)內容如下:

router.beforeEach((to,?from,?next)?=>?{
??NProgress.start()
??if?(getToken())?{
????to.meta.title?&&?useSettingsStore().setTitle(to.meta.title)
????/*?has?token*/
????if?(to.path?===?'/login')?{
??????next({?path:?'/'?})
??????NProgress.done()
????}?else?{
??????if?(useUserStore().roles.length?===?0)?{
????????isRelogin.show?=?true
????????//?判斷當前用戶是否已拉取完user_info信息
????????useUserStore().getInfo().then(()?=>?{
??????????isRelogin.show?=?false
??????????usePermissionStore().generateRoutes().then(accessRoutes?=>?{
????????????//?根據(jù)roles權限生成可訪問的路由表
????????????accessRoutes.forEach(route?=>?{
??????????????if?(!isHttp(route.path))?{
????????????????router.addRoute(route)?//?動態(tài)添加可訪問路由表
??????????????}
????????????})
????????????next({?...to,?replace:?true?})?//?hack方法?確保addRoutes已完成
??????????})
????????}).catch(err?=>?{
??????????useUserStore().logOut().then(()?=>?{
????????????ElMessage.error(err)
????????????next({?path:?'/'?})
??????????})
????????})
??????}?else?{
????????next()
??????}
????}
??}?else?{
????//?沒有token
????if?(whiteList.indexOf(to.path)?!==?-1)?{
??????//?在免登錄白名單,直接進入
??????next()
????}?else?{
??????next(`/login?redirect=${to.fullPath}`)?//?否則全部重定向到登錄頁
??????NProgress.done()
????}
??}
})

我跟大家捋一下這個前置導航守衛(wèi)中的思路:

  • 首先調用 getToken 方法,這個方法實際上是去 Cookie 中拿認證 Token,也就是登錄成功后后端返回給前端的那個 JWT 字符串。
  • 如果 getToken 方法有返回值,說明用戶已經登錄了,那么進入到 if 分支中,如果 getToken 沒拿到值,說明用戶未登錄,未登錄的話,又分為兩種情況:i:訪問的目標地址處于免登錄白名單中,那么此時直接訪問即可;ii:訪問的目標地址不在白名單中,那么此時就跳轉到登錄頁面去,跳轉的時候同時攜帶一個 redirect 參數(shù),這樣方便在登錄成功之后,再跳轉回訪問的目標頁面。這個免登錄訪問的白名單,是一個在 src/permission.js 文件中定義的變量,默認有四個路徑,分別是 ['/login', '/auth-redirect', '/bind', '/register']
  • 如果 getToken 拿到了值,說明用戶已經登錄了,此時又分情況:如果用戶訪問的路徑是登錄頁面,那么就給他重定向到項目首頁(也就是在已經登錄的情況下,不允許用戶再次訪問登錄頁面);如果用戶訪問的路徑不是登錄頁面,那么首先判斷 vuex 中的 roles 是否還有值?如果有值,說明當前就是用戶點擊了一個菜單按鈕進行跳轉的,那么直接跳轉就行了;如果沒有值,說明用戶是按了瀏覽器的刷新按鈕或者是 F5 按鈕刷新進行的頁面跳轉,那么此時首先調用 getInfo 方法(位于 src/store/modules/user.js 文件中)去服務端重新加載當前用戶的基本信息、角色信息以及權限信息,然后再調用 generateRoutes 方法(位于 src/store/modules/permission.js 文件中)去服務端加載路由信息,并將加載到的路由信息放入到 router 對象中(前提是這個路由對象不是一個 http 鏈接,就是普通的路由地址)。

這就是動態(tài)路由的加載整體思路。

在第三步驟中,涉及到兩個方法,一個是 getInfo 還有一個 generateRoutes,這兩個方法也都比較關鍵,我們再來稍微看下。

2.2 getInfo

首先這個加載用戶信息的方法位于 src/store/modules/user.js 文件中,換言之,這些用戶的基本信息加載到之后,是存儲在 vuex 中的,如果刷新瀏覽器這些數(shù)據(jù)就會丟失:

getInfo()?{
??return?new?Promise((resolve,?reject)?=>?{
????getInfo().then(res?=>?{
??????const?user?=?res.user
??????const?avatar?=?(user.avatar?==?""?||?user.avatar?==?null)???defAva?:?import.meta.env.VITE_APP_BASE_API?+?user.avatar;
??????if?(res.roles?&&?res.roles.length?>?0)?{?//?驗證返回的roles是否是一個非空數(shù)組
????????this.roles?=?res.roles
????????this.permissions?=?res.permissions
??????}?else?{
????????this.roles?=?['ROLE_DEFAULT']
??????}
??????this.name?=?user.userName
??????this.avatar?=?avatar;
??????resolve(res)
????}).catch(error?=>?{
??????reject(error)
????})
??})
},

方法的邏輯其實倒沒啥好說的,結合服務端返回的 JSON 格式,應該就很好理解了(部分 JSON):

{
????"permissions":[
????????"*:*:*"
????],
????"roles":[
????????"admin"
????],
????"user":
????????"userName":"admin",
????????"nickName":"TienChin健身",
????????"avatar":"",
????}
}

另外再強調下,之前在 vhr 中,我們是將請求封裝成了一個 api.js 文件,里邊有常用的 get、post、put 以及 delete 請求等,然后在需要使用的地方,直接去調用這些方法發(fā)送請求即可,但是在 TienChin 中,腳手架的封裝是將所有的請求都提前統(tǒng)一封裝好,在需要的時候直接調用封裝好的方法,連請求地址都不用傳遞了(封裝的時候就已經寫死了),所以小伙伴們看上面的 getInfo 方法只有方法調用,沒有傳遞路徑參數(shù)等。

2.3 generateRoutes

generateRoutes 方法則位于 src/store/modules/permission.js 文件中,這里值得說道的地方就比較多了:

generateRoutes(roles)?{
??return?new?Promise(resolve?=>?{
????//?向后端請求路由數(shù)據(jù)
????getRouters().then(res?=>?{
??????const?sdata?=?JSON.parse(JSON.stringify(res.data))
??????const?rdata?=?JSON.parse(JSON.stringify(res.data))
??????const?defaultData?=?JSON.parse(JSON.stringify(res.data))
??????const?sidebarRoutes?=?filterAsyncRouter(sdata)
??????const?rewriteRoutes?=?filterAsyncRouter(rdata,?false,?true)
??????const?defaultRoutes?=?filterAsyncRouter(defaultData)
??????const?asyncRoutes?=?filterDynamicRoutes(dynamicRoutes)
??????asyncRoutes.forEach(route?=>?{?router.addRoute(route)?})
??????this.setRoutes(rewriteRoutes)
??????this.setSidebarRouters(constantRoutes.concat(sidebarRoutes))
??????this.setDefaultRoutes(sidebarRoutes)
??????this.setTopbarRoutes(defaultRoutes)
??????resolve(rewriteRoutes)
????})
??})
}

首先大家看到,服務端返回的動態(tài)菜單數(shù)據(jù)解析了三次,分別拿到了三個對象,這三個對象都是將來要用的,只不過使用的場景不同,下面結合頁面的顯示跟大家細說。

  • 首先是調用 filterAsyncRouter 方法,這個方法的核心作用就是將服務端返回的 component 組件動態(tài)加載為一個 component 對象。不過這個方法在調用的過程中,后面還有兩個參數(shù),第二個是 lastRouter 在該方法中并無實質性作用;第三個參數(shù)則主要是說是否需要對 children 的 path 進行重寫。小伙伴們知道,服務端返回的動態(tài)菜單的 path 屬性都是只有一層的,例如一級菜單系統(tǒng)管理的 path 是 system,二級菜單用戶管理的 path 則是 user,那么用戶管理最終訪問的 path 就是 system/path,如果第三個參數(shù)為 true,則會進行 path 的重寫,將 path 最終設置正確。
  • 所以這里的 sidebarRoutes 和 defaultRoutes 只是能用于菜單渲染(因為這兩個里邊的菜單 path 不對),而最終的頁面跳轉要通過 rewriteRoutes 才可以實現(xiàn)。
  • 除了服務端返回的動態(tài)菜單,前端本身也定義了一些基礎菜單,前端的基礎菜單分為兩大類,分別是 constantRoutes 和 dynamicRoutes,其中 constantRoutes 是固定菜單,也就是一些跟用戶權限無關的菜單,例如 404 頁面、首頁等;dynamicRoutes 是動態(tài)菜單,也就是也根據(jù)用戶權限來決定是否展示的菜單,例如分配用戶、字典數(shù)據(jù)、調度日志等等。
  • filterDynamicRoutes 方法則是將前端提前定義好的 dynamicRoutes 菜單進行過濾,找出那些符合當前用戶權限的菜單將之添加到路由中(這些菜單都不需要在菜單欄渲染出來)。
  • 接下來涉及到四個不同的保存路由數(shù)據(jù)的變量,分別是 routes、addRoutes(經松哥分析,這個變量并無實際作用,可以刪除之)、defaultRoutes、topbarRouters 以及 sidebarRouters,四個路由變量的作用各有不同:

routes:

routes 中保存的是 constantRoutes 以及服務端返回的動態(tài)路由數(shù)據(jù),并且這個動態(tài)路由數(shù)據(jù)中的 path 已經完成了重寫,所以這個 routes 主要用在兩個地方:

首頁的搜索上:首頁的搜索也可以按照路徑去搜索,所以需要用到這個 routes,如下圖:

用在 TagsView,這個地方也需要根據(jù)頁面渲染不同的菜單,也是用的 routes:

sidebarRouters:

這個就是大家所熟知的側邊欄菜單了,具體展示是 constantRoutes+服務端返回的菜單,不過這些 constantRoutes 基本上 hidden 屬性都是 false,渲染的時候是不會被渲染出來的。

topbarRouters:

這個是用在 TopNav 組件中,這個是將系統(tǒng)的一級菜單在頭部顯示出來的,如下圖:

一級菜單在頂部顯示,左邊顯示的都是二級三級菜單,那么頂部菜單的渲染,用的就是這個 topbarRouters。

defaultRoutes:

想要開啟頂部菜單,需要在 src/layout/components/Settings/index.vue 組件中設置,如下圖:

開啟頂部菜單之后,點擊頂部菜單,左邊菜單欄會跟著切換,此時就是從 defaultRoutes 中遍歷出相關的菜單設置給 sidebarRouters。

好了,這就是這四個 routes 變量的作用,老實說,腳手架中這塊的代碼設計有點混亂,沒必要搞這么多變量,等松哥抽空給大家優(yōu)化下。

generateRoutes 方法最終會返回 rewriteRoutes 變量到前面說的那個前置導航守衛(wèi)中,最終前置導航守衛(wèi)將數(shù)據(jù)添加到 router 中。

菜單的渲染都是在 src/layout/components/Sidebar/index.vue 中完成的,看了下都是常規(guī)操作,沒啥好說的。

到此這篇關于詳解Vue3如何加載動態(tài)菜單的文章就介紹到這了,更多相關Vue3加載動態(tài)菜單內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • Vue中的v-model,v-bind,v-on的區(qū)別解析

    Vue中的v-model,v-bind,v-on的區(qū)別解析

    vue.js是一套構建用戶界面的框架,只關注視圖層,它不僅易于上手,還便于與第三方庫或既有項目整合,vue.js有配套的第三方類庫,可以整合起來做大型項目的開發(fā),這篇文章主要介紹了v-model,v-bind,v-on的區(qū)別,需要的朋友可以參考下
    2022-12-12
  • Element表格表頭行高問題解決

    Element表格表頭行高問題解決

    在最近一個項目的后臺管理系統(tǒng)中,寫前端界面時用到了ElementUI,但是發(fā)現(xiàn)導入數(shù)據(jù)表格之后表頭的高度一直很高,那么如何解決,本文就來詳細的介紹一下
    2021-09-09
  • vue 使用post/get 下載導出文件操作

    vue 使用post/get 下載導出文件操作

    這篇文章主要介紹了vue 使用post/get 下載導出文件操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-08-08
  • vue+element 實現(xiàn)商城主題開發(fā)的示例代碼

    vue+element 實現(xiàn)商城主題開發(fā)的示例代碼

    這篇文章主要介紹了vue+element 實現(xiàn)商城主題開發(fā)的示例代碼,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-03-03
  • Vue實現(xiàn)無縫輪播效果

    Vue實現(xiàn)無縫輪播效果

    這篇文章主要為大家詳細介紹了Vue實現(xiàn)無縫輪播效果,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-04-04
  • 用vue寫一個仿簡書的輪播圖的示例代碼

    用vue寫一個仿簡書的輪播圖的示例代碼

    本篇文章主要介紹了用vue寫一個仿簡書的輪播圖的示例代碼,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-03-03
  • vue中table實現(xiàn)真正的跨越全選

    vue中table實現(xiàn)真正的跨越全選

    本文主要介紹了vue中table實現(xiàn)真正的跨越全選,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2023-05-05
  • 詳解從Vue-router到html5的pushState

    詳解從Vue-router到html5的pushState

    這篇文章主要介紹了詳解從Vue-router到html5的pushState,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-07-07
  • vite項目import.meta.env如何能獲取非VITE開發(fā)的環(huán)境變量

    vite項目import.meta.env如何能獲取非VITE開發(fā)的環(huán)境變量

    這篇文章主要介紹了vite項目import.meta.env如何能獲取非VITE開發(fā)的環(huán)境變量問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-05-05
  • 詳解vue-cli3多環(huán)境打包配置

    詳解vue-cli3多環(huán)境打包配置

    這篇文章主要介紹了vue-cli3多環(huán)境打包配置,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2019-03-03

最新評論