中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Vue項目全局配置頁面緩存之按需讀取緩存的實現詳解

發布時間:2020-10-16 10:36:38 來源:腳本之家 閱讀:169 作者:FrankCheung 欄目:web開發

寫在前面

一個web app的實際使用場景中,有一些情景的交互要求,是記錄用戶的瀏覽狀態的。最常見的就是在列表頁進入詳情頁之后,再返回到列表頁,用戶希望返回到進入詳情頁之前的狀態繼續操作。但是有些使用場景,用戶又是希望能夠獲取最新的數據,例如同級列表頁之間切換的時候。

如此,針對上述兩種使用場景,需要實現按需讀取頁面緩存。由于SPA應用的路由邏輯也是在前端實現的,因此可以在前端對路由的邏輯進行設置以實現所需效果。

使用技術

  • Vue.js作為主要框架
  • Vue-router作為前端路由管理器
  • Vuex作為狀態管理工具

總體思路

keep-alive判斷當前組件是否讀取緩存的節點,在整個生命周期里面非常靠后,在afterEach之后,基本在組件實例創建之前。(因此在此之前對當前組件是否讀取緩存進行處理都是可行的,我選擇在全局前置守衛進行處理)

而判斷當前組件是否緩存的節點,則早于組件的beforeRouteLeave鉤子。

基于上述邏輯,本方案解決的邏輯是,對當前打開的頁面進行判斷,動態生成需要keepAlive的組件數組配置,對有可能需要緩存的先行進行緩存,然后在每次路由切換的時候,再進行判斷,按需讀取頁面緩存。

  1. 使用kepp-alive進行緩存,使用include屬性對需要緩存的頁面進行配置。
  2. 由于需要緩存的頁面配置系動態生成,所以使用vuex儲存該配置。
  3. 在路由元信息中寫入兩個配置,一是該路由是否需要緩存,二是從相關路由進入時才進行緩存的特定路由數組。
  4. 在beforeEach進行設置,每次進入路由之前,對進入的路由及其所有父級路由進行判斷,若需要緩存且命中特定路由數組,則將相關路由添加至緩存配置文件中;若不符合,則將相關路由刪除。(此步驟實現了路由切換時,需要則讀取緩存,不需要則重新獲取數據。)
  5. 使用全局mixin,進入相關組件之前,對當前路由進行判斷,如果需要緩存的則將該路由添加至緩存配置中。(此步驟實現了緩存當前打開的需要緩存的頁面。)

具體實現

1. 使用include屬性控制路由緩存

此處需要注意的是,include匹配首先檢查組件自身的 name 選項,如果 name 選項不可用,則匹配它的局部注冊名稱 (父組件 components 選項的鍵值)。匿名組件不能被匹配。

但是vue-router的環境下,是沒有局部注冊名稱的,只能為組件補全name屬性。

因此,請務必給組件添加 name 選項,否則匿名組件將全部應用緩存。

<keep-alive :include="$store.state.cachedRouteNames">
 <router-view />
</keep-alive>

2. 添加全局路由緩存配置

// store/index.js

const store = new vuex.Store({
 state: {
 // 緩存的路由列表
 cachedRouteNames: [],
 },
 mutations: {
 UPDATE_CACHEDROUTENAMES(state,{ action, route }) {
  const methods = {
  'add': () => {
  state.cachedRouteNames.push(route)
  },
  'delete': () => {
  state.cachedRouteNames.splice(state.cachedRouteNames.findIndex((e) => { return e === route}),1)
  }
  }
  methods[action]()
 }
 }
})

3. 配置路由元信息,對需要緩存的路由進行配置

keepAlive表明路由需要被緩存,必須,否則不緩存

cacheWhenFromRoutes為數組,非必須,若為falsy值,則任何時候均緩存;若為空數組,則任何時候均不緩存

// router/index.js

{
 path: '/productslist',
 name: 'ProductsList',
 component: ProductsList,
 meta: {
 keepAlive: true,
 cacheWhenFromRoutes: ['ProductDetail'] // 此處配置的是路由的name
 }
},

4. 配置全局前置守衛,按需讀取緩存

// routeControl.js

// 需要緩存的路由名稱數組
const cachedRouteNames = store.state.cachedRouteNames;

// 定義添加緩存組件name函數,設置的是組件的name
const addRoutes = (route) => {
 const routeName = route.components.default.name
 if (routeName && cachedRouteNames.indexOf(routeName) === -1) {
 store.commit('UPDATE_CACHEDROUTENAMES', { action: 'add', route: routeName })
 }
}

// 定義刪除緩存組件name函數,設置的是組件的name
const deleteRoutes = (route) => {
 const routeName = route.components.default.name
 if (routeName && cachedRouteNames.indexOf(routeName) !== -1) {
 store.commit('UPDATE_CACHEDROUTENAMES', { action: 'delete', route: routeName })
 }
}

router.beforeEach((to, from, next) => {
 
 // 處理緩存路由開始
 // 在讀取緩存之前,先對該組件是否讀取緩存進行處理
 to.matched.forEach((item, index) => {
 const routes = item.meta.cacheWhenFromRoutes;
 /**
  * 此處有幾種情況
  * 1. 沒有配置cacheWhenFromRoutes, 則一直緩存;
  * 2. 配置了cacheWhenFromRoutes,但是首次打開此web app,則from.name為空,此時應該將該頁面組件的name添加到緩存配置文件中
  * 3. 配置了cacheWhenFromRoutes,from.name不為空,若命中cacheWhenFromRoutes,則添加該頁面組件的name到緩存配置文件中,否則刪除。
  *
  **/
 if (item.meta.keepAlive && (!routes || (routes && (!from.name || routes.indexOf(from.name) !== -1)))) {
  addRoutes(item)
 } else {
  deleteRoutes(item)
 }
 
 })
 // 處理緩存路由結束

 new Promise(( resolve, reject ) => {
 // ..other codes
 }).then( res => {
 if ( res ) {
  next(res)
 } else {
  next()
 }
 })
})

// 全局混入。此步驟的目的是在該組件被解析之后,若是屬于需要緩存的組件,先將其添加到緩存配置中,進行緩存。

// 導航守衛的最后一個步驟就是調用 beforeRouteEnter 守衛中傳給 next 的回調函數,此時整個組件已經被解析,DOM也已經更新。

Vue.mixin({
 beforeRouteEnter(to, from, next) {
 next(vm => {
  to.matched.forEach((item) => {
  const routeName = item.components.default.name
  if (to.meta.keepAlive && routeName && cachedRouteNames.indexOf(routeName) === -1) {
   store.commit('UPDATE_CACHEDROUTENAMES', { action: 'add', route: routeName })
  }
  })
 })
 },
})

寫在最后

坑點

  • 此方案涉及兩個name,一個是設置特定路由時,使用路由的name。另一個是動態生成緩存配置文件時,使用的是頁面組件的name。
  • 務必給組件添加name屬性,便于include屬性的使用,也方便調試跟蹤。如果組件缺少name屬性,將會默認使用緩存。
  • 動態處理緩存配置時,一定要對to.matched進行遍歷,否則嵌套路由的父級路由的緩存就無法生效,將導致子路由的緩存也無法生效。
  • 全局混入有一定危險性,慎用...

以上是實踐過程中摸索出來的一種解決方案,我相信存在更加優雅高效的解決方式。如果你正好實踐過相關方法,煩請指正,謝謝。

更多參考

github.com/vuejs/vue/i…

總結

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對億速云的支持。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

正宁县| 雅安市| 河间市| 温宿县| 平泉县| 民乐县| 江陵县| 五大连池市| 阳原县| 自贡市| 绩溪县| 喜德县| 寿阳县| 郑州市| 普宁市| 泾源县| 庐江县| 蓬莱市| 洪江市| 阳江市| 宁远县| 成武县| 靖安县| 中方县| 武汉市| 新邵县| 富阳市| 正镶白旗| 大连市| 扎兰屯市| 清原| 绵阳市| 天门市| 游戏| 凤阳县| 鄂尔多斯市| 巍山| 万安县| 班玛县| 平果县| 共和县|