vue移動端專案中如何實現頁面快取的示例程式碼
背景
在移動端中,頁面跳轉之間的快取是必備的一個需求。
例如:首頁=>列表頁=>詳情頁。
從首頁進入列表頁,列表頁需要重新整理,而從詳情頁返回列表頁,列表頁則需要保持頁面快取。
對於首頁,一般我們都會讓其一直保持快取的狀態。
對於詳情頁,不管從哪個入口進入,都會讓其重新重新整理。
實現思路
說到頁面快取,在vue中那就不得不提keep-alive元件了,keep-alive提供了路由快取功能,本文主要基於它和vuex來實現應用裡的頁面跳轉快取。
vuex裡維護一個數組cachePages,用以儲存當前需要快取的頁面。
keep-alive 的 includes 設定為ca程式設計客棧
路由meta新增自定義欄位 needCachePages或keepAlive,needCachePages 為一個數組,表示該路由要進入的頁面如果在陣列內,則快取該路由,keepAlive則表示無論進入哪個頁面都保持快取,如app首頁這種。
在路由守衛beforeEach裡判斷,如果要跳轉的路由頁面在當前路由的needCachePages裡,則當前路由新增進cachePages裡,反之刪除。
具體實現
vuex實現內容
// src/store/modules/app.js export default { state: { // 頁面快取陣列 cachePages: [] },mutations: { // 新增快取頁面 ADD_CACHE_PAGE(state,page) { if (!state.cachePages.includes(page)) { state.cachePages.push(page) } },// 刪除快取頁面 REMOVE_CACHE_PAGE(state,page) { if (state.cachePages.includes(page)) { state.cachePages.splice(state.cachePages.indexOf(page),1) } } } }
// src/store/getters.js const getters = { cachePages: state => state.app.cachePages } export default getters
// src/store/index.js import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex) import user from './modules/user' import app from './modules/app' import getters from './getters' // 匯出 store 物件 export default new Vuex.Store({ getters,modules: { user,app } })
App.vue裡,keep-alive的include設定cachePages
<keep-alive :include="cachePhttp://www.cppcns.comages"> <router-view :key="$route.fullPath"></router-view> </keep-alive> computed: { ...mapGett程式設計客棧ers([ 'cachePages' ]) }
路由配置
{ path: '/home',name: 'Home',component: () => import('@/views/tabbar/Home'),meta: { title: '首頁',keepAlive: true } },{ path: '/list',name: 'List',component: () => import('@/views/List'),meta: { title: '列表頁',needCachePages: ['ListDetail'] } },{ path: '/list-detail',name: 'ListDetail',component: () => import('@/views/Detail'),meta: { title: '詳情頁' } }
路由守衛
import Vue from 'vue'
import Router from 'vue-router'
import store from '@/store'
Vue.use(Router)
// 匯入modules資料夾裡的所有路由
const files = require.context('./modules',false,/\.js$/)
let modules = []
files.keys().forEach(key => {
modules = modules.concat(files(key).default)
})
// 路由
const routes = [
{
path: '/',redirect: '/howww.cppcns.comme',},...modules
]
const router = new Router({
mode: 'hash',routes: routes
})
function isKeepAlive(route) {
if (route.meta && route.meta.keepAlive) {
store.commit('ADD_CACHE_PAGE',route.name)
}
if (route.children) {
route.children.forEach(child => {
isKeepAlive(child)
})
}
}
routes.forEach(item => {
isKeepAlive(item)
})
// 全域性路由守衛
router.beforeEach((to,from,next) => {
if (from.meta.needCachePages && from.meta.needCachePages.includes(to.name)) {
store.commit('ADD_CACHE_PAGE',from.name)
} else if (from.meta.needCachePages) {
store.commit('REMOVE_CACHE_PAGE',from.name)
}
// 出現頁面首次快取失效的情況,猜測是vuex到keep-alive快取有延遲的原因
//這裡使用延遲100毫秒解決
setTimeout(() => {
next()
},100)
})
export default router
還原頁面滾動條位置
此時雖然頁面實現快取了,但滾動條每次都會重新回到頂部。
對於快取的頁面,會觸發activated和deactivated這兩個鉤子,可以利用這兩個鉤子來實現還原滾動條位置。
在頁面離開時,也就是deactivated觸發時記錄滾動條位置。
在重新回到頁面時,也就是activated觸發時還原滾動條位置。
// 建立一個mixin //http://www.cppcns.com src/mixins/index.js export const savePosition = (scrollId = 'app') => { return { data() { return { myScrollTop: 0 } },activated() { const target = document.getElementById(scrollId) target && target.scrollTop = this.myScrollTop },beforeRouteLeave(to,next) { const target = document.getElementById(scrollId) this.myScrollTop = target.scrollTop || 0 next() } } }
這裡發現使用deactivated時會因為頁面隱藏過快會導致獲取的節點滾動條高度為0,所以用beforeRouteLeave。
在需要快取的頁面中使用
<script> import { savePosition } from '@/mixins' export default { mixins: [new savePosition()] } </script>
如果頁面自定義了滾動容器,此時可以傳入滾動容器id
<template> <div id="scroll-container" style="height: 100vh; overflow-y: scroll;"> </div> </template> <script> import { savePosition } from '@/mixins' export default { mixins: [new savePosition('scroll-container')] } </script>
注意
我的小夥伴經常會來問我一個問題,為什麼我配置了卻沒有快取的效果?
這個時候你就需要注意一個問題了,keep-alive的一個關鍵是路由裡的name要和.vue檔案裡的name保持一致。
如果你的快取沒有生效,請首先檢查一下兩個name和needCachePages裡是否一致。
思考與不足
此方案是我一年多前的做法,現在想來其實還是存在一些不足的,比如每次都需要去配置路由裡的needCachePages。
而實際上在移動端中,往往都是在返回上一頁時,上一頁始終保持快取的狀態,就如開發小程式時一樣,當我們呼叫navigateTo後再返回,頁面始終是快取的並不需要任何人為的配置。
所以現在的想法是,在vue中提供一個全域性的跳轉api,只要呼叫該api就把當前頁面快取,如果需要重新整理操作,可以像小程式裡的onShow一樣在activated裡執行你的邏輯。
到此這篇關於vue移動端專案中如何實現頁面快取的示例程式碼的文章就介紹到這了,更多相關vue 頁面快取內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!