vue移动端项目中如何实现页面缓存的示例代码
背景
在移动端中,页面跳转之间的缓存是必备的一个需求。
例如:首页=>列表页=>详情页。
从首页进入列表页,列表页需要刷新,而从详情页返回列表页,列表页则需要保持页面缓存。
对于首页,一般我们都会让其一直保持缓存的状态。
对于详情页,不管从哪个入口进入,都会让其重新刷新。
实现思路
说到页面缓存,在vue中那就不得不提keep-alive组件了,keep-alive提供了路由缓存功能,本文主要基于它和vuex来实现应用里的页面跳转缓存。
vuex里维护一个数组cachePages,用以保存当前需要缓存的页面。
keep-alive 的 includes 设置为cachePages。
路由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="cachePages"> <router-view :key="$route.fullPath"></router-view> </keep-alive> computed: { ...mapGetters([ '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: '/home', }, ...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 // 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, from, 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 页面缓存内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
您可能感兴趣的文章:- VUE页面中通过双击实现复制表格中内容的示例代码
- Vue项目全局配置页面缓存之按需读取缓存的实现详解
- SpringBoot项目如何访问jsp页面的示例代码
- vue使用原生js实现滚动页面跟踪导航高亮的示例代码
- Vue中组件的使用小技巧(移动端 去哪网项目的搭建及简单页面实现)
- vue-cli实现多页面多路由的示例代码
- Vue中如何实现轮播图的示例代码
- 转:如何在Vue项目中使用vw实现移动端适配
- 如何在Vue项目中使用vw实现移动端适配
- Vue+mui实现图片的本地缓存示例代码
- vue项目tween方法实现返回顶部的示例代码
- 如何在项目里面使用freemarker实现页面缓存(三)
- Java如何实现长图文生成的示例代码
- 网络应用系统---系统设计架构个人项目实战示例(各种页面代码A)
- SkylineGlobe 6.5 如何实现简单多边形的动态绘制 C#示例代码
- 本地vue项目放到github如何实现在线预览
- vue实现仿淘宝结账页面实例代码
- AjaxPanel自定义控件实现页面无刷新数据交互(做了个示例程序, 效果确实比较Cool, 用法非常简单! )(示例代码下载)
- 使用原生js实现页面蒙灰(mask)效果示例代码
- 原生js实现移动端瀑布流式代码示例