您好,登錄后才能下訂單哦!
寫在前面
一個web app的實際使用場景中,有一些情景的交互要求,是記錄用戶的瀏覽狀態的。最常見的就是在列表頁進入詳情頁之后,再返回到列表頁,用戶希望返回到進入詳情頁之前的狀態繼續操作。但是有些使用場景,用戶又是希望能夠獲取最新的數據,例如同級列表頁之間切換的時候。
如此,針對上述兩種使用場景,需要實現按需讀取頁面緩存。由于SPA應用的路由邏輯也是在前端實現的,因此可以在前端對路由的邏輯進行設置以實現所需效果。
使用技術
總體思路
keep-alive判斷當前組件是否讀取緩存的節點,在整個生命周期里面非常靠后,在afterEach之后,基本在組件實例創建之前。(因此在此之前對當前組件是否讀取緩存進行處理都是可行的,我選擇在全局前置守衛進行處理)
而判斷當前組件是否緩存的節點,則早于組件的beforeRouteLeave鉤子。
基于上述邏輯,本方案解決的邏輯是,對當前打開的頁面進行判斷,動態生成需要keepAlive的組件數組配置,對有可能需要緩存的先行進行緩存,然后在每次路由切換的時候,再進行判斷,按需讀取頁面緩存。
具體實現
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 }) } }) }) }, })
寫在最后
坑點
以上是實踐過程中摸索出來的一種解決方案,我相信存在更加優雅高效的解決方式。如果你正好實踐過相關方法,煩請指正,謝謝。
更多參考
github.com/vuejs/vue/i…
總結
以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對億速云的支持。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。