瀟瀟灑灑寫一個KeepAlive動態緩存組件

大家好呀,我是wangly。一名不怎麼摸魚的前端小倒黴蛋。前端

這篇文章主要寫了一下大部分Admin系統中常見的動態緩存組件,說通俗一點就是TagsBar組件。能夠看下@panjiachen大佬Admin項目。集成在一完整項目中的組件或多或少會依賴一些其餘的東西,這一次就開始從零實現這個功能吧。源碼在底部,每一步都附待思路圖哦。vue

效果圖
效果圖

開始

畫了一張很水的圖,其實整個過程很簡單,進入頁面路由後,判斷當前路由是不是在白名單中,像登陸頁面,404等頁面是不須要被緩存的。只有後臺管理系統的頁面須要緩存,那麼就將當前路由信息緩存到Vuex的緩存區。在經過緩存區的內容生成keep-aliveinclude的匹配條件。同時根據緩存區的內容生成標籤。那麼下面就開始吧git

流程圖
流程圖
效果演示圖
效果演示圖

進入路由後

爲何不在進入頁面前,個人考慮是,只有真正到達了路由了纔算是進入頁面。因此說,在路由的after鉤子中進行操做。github

router.afterEach((to, from) => {
 // ... 判斷是否在白名單  // ... 添加緩存區 }) 複製代碼

是否在白名單

驗證是不是一些在白名單的路由。像基本的登錄頁面,404時不要進行緩存的。所以須要過濾掉它。其次在經過一個Mutations方法changeCacheKeepMap修改和添加緩存的路由組件。web

router.afterEach((to, from) => {
 if (!whitePath.includes(to.path)) {  Store.commit('changeCacheKeepMap', to)  } }) 複製代碼

添加到緩存區

vuex中的changeCacheKeepMap主要是對statecacheKeepMapMap數據進行一個操做。衆所周知,Map是有序的。值是無重複的。在這裏很是適合做爲主要數據結構。在這裏Mapkey設置爲路由的名稱。內容就是路由信息。須要注意的是,Vue對於Map的支持較差,因此只能直接從新覆蓋原數據才能進行響應式。這裏是一個坑點。vuex

路由名稱 = 組件名稱,這一步很重要。由於它是做爲KeepAlive組件緩存的依據。沒有這個依據,就上不了車。數組

/**  * 添加緩存組件信息  * @param {RouteConfig} route  */ changeCacheKeepMap(state, route) {  const swapMap = new Map(state.cacheKeepMap)  swapMap.set(route.name, route)  state.cacheKeepMap = swapMap } 複製代碼
Vuex數據
Vuex數據

緩存router-view

經過keep-aliveinclude來進行組件緩存憑證。須要在緩存的頁面中標明name屬性。 filterIncludeComponentName計算屬性主要是將Map存放的key所有匯聚成爲一個數組。做爲include的條件。緩存

// DOM
 <keep-alive :include="filterIncludeComponentName">  <router-view/> </keep-alive>  // filterIncludeComponentName計算屬性 filterIncludeComponentName () {  const componentNames = []  for (const key of this.cacheKeepMap.keys()) {  componentNames.push(key)  }  return componentNames } 複製代碼
緩存組件
緩存組件

include 使該標籤做用於全部name屬性的值跟此標籤 include 的屬性值一致的vue頁面數據結構

頂部標籤生成

這裏就簡單的多了,經過v-for遍歷出Mapkeyvalue,很是的簡單。而後設置標題,給route-link綁定to。經過當前路由的namelabel進行當前路由的判斷。這裏邏輯很是簡單。編輯器

<router-link
 class="header-menu__item"  :to="value.path"  :class="$route.name === label && 'is-active'"  tag="li"  v-for="[label, value] in cacheKeepMap"  :key="label" >  <a-badge :status="$route.name === label ? 'processing' : 'default'" />  <span class="tag-text">{{value.meta.title}}</span>  <a-icon type="close" @click.stop="onCloseTag(label)" class="close-btn" /> </router-link>  複製代碼

擴展...

還有須要擴展的功能對於你們來講,是能夠擴展的。好比清除緩存區,緩存區更新啥的。都是根據本身的需求來定義。若是你看完了文章,那麼這些都難不住你。正所謂,知其一而知其三,方爲學習。根據本身的思考,去擴展本身想要的功能,自己就是一種進步。

總結

本篇文章屬於簡單的技術分享文,若是對你有用,不妨給我點個贊吧。最近一直都是在看其餘的資料,和準備編寫一本小冊。一些項目都懶散了。每週幾篇文章總結仍是有的。之後會多多更新的。

下面附上源碼地址給你們參考:

源碼項目:連接

EleganceUI 求星星:連接

相關文章
相關標籤/搜索