背景介紹
最近在做公司后臺(tái)管理系統(tǒng)項(xiàng)目時(shí)遇到一個(gè)比較怪異的bug——采用keep-alive+vue-router
實(shí)現(xiàn)的路由緩存遇到緩存不生效的情況泣刹。
項(xiàng)目背景
此項(xiàng)目是基于iview-admin@2.0進(jìn)行開發(fā)的助析,全局狀態(tài)管理采用vuex分module實(shí)現(xiàn),路由采用vue-router進(jìn)行路由配置表的方式實(shí)現(xiàn)椅您。
項(xiàng)目屬于基于RBAC的后臺(tái)管理系統(tǒng)貌笨,需要多用戶多角色的權(quán)限控制,同時(shí)路由功能菜單以及展示的字段需按角色劃分襟沮,因此左側(cè)系統(tǒng)菜單根據(jù)接口進(jìn)行動(dòng)態(tài)設(shè)置锥惋。
項(xiàng)目中可以進(jìn)行菜單的圖標(biāo)、跳轉(zhuǎn)路徑开伏、是否隱藏等進(jìn)行配置膀跌,路徑對(duì)應(yīng)的前端路由則由前端的路由記錄進(jìn)行管理,即菜單管理功能設(shè)置的跳轉(zhuǎn)路徑是否可用由此路由記錄決定固灵。
解決過程
核實(shí)路由緩存用法問題
發(fā)現(xiàn)這個(gè)bug之后梳理了一遍路由組件緩存的實(shí)現(xiàn)方案捅伤,同時(shí)仔細(xì)核對(duì)了一遍vue-router的官方文檔
官方推薦的用法如下:
<transition>
<keep-alive>
<router-view></router-view>
</keep-alive>
</transition>
可以排除基本用法的問題,如是繼續(xù)翻閱vue的官方文檔巫玻,keep-alive的緩存匹配原理是根據(jù)組件的name作為key來(lái)進(jìn)行緩存丛忆,官方的提示
隨即檢查代碼中的路由記錄的name以及對(duì)應(yīng)component的name祠汇,發(fā)現(xiàn)都有定義好,因此排除基本用法的錯(cuò)誤導(dǎo)致熄诡。
iview-admin的不完善導(dǎo)致
進(jìn)行上述問題排查后定位到此問題出在keep-alive組件的include參數(shù)處可很,keep-alive的參數(shù)說(shuō)明如下:
include
- 字符串或正則表達(dá)式。只有名稱匹配的組件會(huì)被緩存凰浮。exclude
- 字符串或正則表達(dá)式我抠。任何名稱匹配的組件都不會(huì)被緩存。max
- 數(shù)字袜茧。最多可以緩存多少組件實(shí)例菜拓。
iview-admin@2.0中通過路由的meata參數(shù)——notCache來(lái)控制路由對(duì)應(yīng)的組件是否進(jìn)行緩存,其源碼中有如下注釋說(shuō)明:
設(shè)為true后頁(yè)面在切換標(biāo)簽后不會(huì)緩存笛厦,如果需要緩存纳鼎,無(wú)需設(shè)置這個(gè)字段,而且需要設(shè)置頁(yè)面組件name屬性和路由配置的name一致
其文檔文檔上關(guān)于路由meta參數(shù)的說(shuō)明在這里裳凸。
其注釋說(shuō)明說(shuō)要讓組件實(shí)現(xiàn)緩存必須要保證頁(yè)面組件的name和路由配置的name一致贱鄙,而該項(xiàng)目中路由配置根據(jù)由后臺(tái)設(shè)置功能決定,故修改不能緩存的頁(yè)面的路由配置的namne即可解決問題登舞。
僅僅是解決了此bug總感覺還不夠贰逾,不如順便研究一個(gè)iview-admin的源碼是如何實(shí)現(xiàn)路由緩存的。
iview-admin實(shí)現(xiàn)路由組件緩存原理
![iview-admin路由組件緩存原理](https://upload-images.jianshu.io/upload_images/4336575-503adabdd2e406c2.png&originHeight=959&originWidth=1397&size=111193&status=done&style=stroke&width=746?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
iview-admin中將navTagList菠秒、menuList等數(shù)據(jù)保存在全局的vuex的app模塊中疙剑,navTagList是當(dāng)前的當(dāng)前打開過的標(biāo)簽頁(yè)數(shù)組根據(jù)路由變化動(dòng)態(tài)更新;menuList是當(dāng)前登錄用戶的菜單數(shù)組践叠,默認(rèn)根據(jù)路由記錄的meta參數(shù)的access字段進(jìn)行過濾
cacheList是app模塊的的getters之一言缤,用戶從tagNavList中計(jì)算出當(dāng)前打開的標(biāo)簽頁(yè)需要用keep-alive緩存的組件name數(shù)組,此處采用的是動(dòng)態(tài)修改keep-alive組件的exclude的值來(lái)動(dòng)態(tài)更新路由的緩存規(guī)則
iview-admin的一些局限
iview-admin中的用戶權(quán)限路由控制思路是:采用路由meata參數(shù)的access數(shù)組來(lái)標(biāo)簽當(dāng)前路由可訪問的用戶角色禁灼,根據(jù)路由記錄計(jì)算出對(duì)應(yīng)用戶的menuList進(jìn)行渲染管挟。
這個(gè)實(shí)現(xiàn)方案存在一些不足:
- 路由采用配置表的方式由前端進(jìn)行配置,路由需要更新時(shí)需要前端更新代碼進(jìn)行打包部署的整套項(xiàng)目發(fā)布流程
- 菜單完全由路由配置即用戶角色計(jì)算得出弄捕,后端不能夠靈活的重置頁(yè)面菜單顯示
基于以上這些考慮對(duì)iview-admin默認(rèn)的權(quán)限控制僻孝、路由配置進(jìn)行如下的優(yōu)化。
考慮優(yōu)化方案
路由分類劃分
項(xiàng)目中的路由組件包括Man.vue進(jìn)行布局控制守谓,404.vue 500.vue等處理前端路由異常的展示穿铆,login.vue error_log.vue等展示用戶注冊(cè)登錄日志記錄等頁(yè)面,這些頁(yè)面路由通常不會(huì)經(jīng)常更新不需要進(jìn)行動(dòng)態(tài)注冊(cè)斋荞,而像其他的復(fù)雜業(yè)務(wù)邏輯處理頁(yè)面需要接口進(jìn)行動(dòng)態(tài)配置荞雏。
故將路由進(jìn)行拆分,基礎(chǔ)路由——routers-common直接配置到router中,業(yè)務(wù)路由——routers進(jìn)行動(dòng)態(tài)注冊(cè)
路由動(dòng)態(tài)注冊(cè)
vuex的store中的user模塊添加獲取用戶路由配置的action——getUserRoutes凤优,在用戶登錄成功后或者或者M(jìn)ain.vue的mounted生命周期中根據(jù)用戶token調(diào)用接口獲取用戶路由配置
調(diào)用router.addRoutes方法進(jìn)行路由的動(dòng)態(tài)注冊(cè)悦陋。
更進(jìn)一步
本文最終對(duì)遇到的vue路由緩存bug進(jìn)行了修復(fù),同時(shí)也對(duì)項(xiàng)目進(jìn)行了一定的優(yōu)化改造筑辨,后續(xù)對(duì)于vue-router源碼的進(jìn)一步研究也已經(jīng)完成俺驶,想知道本文遇到的’坑‘在源碼中是如何’埋下‘的,請(qǐng)閱讀我專欄的下一篇文章——帶你全面分析vue-router源碼(萬(wàn)字長(zhǎng)文)挖垛。
若此文對(duì)你有一點(diǎn)點(diǎn)幫助請(qǐng)點(diǎn)個(gè)贊鼓勵(lì)下作者痒钝,畢竟原創(chuàng)不易:)
首發(fā)自語(yǔ)雀:https://www.yuque.com/johniexu/frontend/dhgooo
作者博客地址:blog.lessing.online/
作者github:github.com/johniexu