vue移动端H5跨页面,缓存方案
1.场景
相信大家在开发移动端的时候或多或少都有需要跨页面(看详情,填表单....) 这样的需求。
这个时候涉及到跨路由就会很头疼。下面分享一个解决方案
2.实现思路
首先还是基于 vue 的keep-alive 去实现
App.vue
<template>
<div id="app">
<keep-alive :include="keepAlivePages">
<router-view ></router-view>
</keep-alive>
</div>
</template>
<script>
export default {
name: 'app',
components: {
},
computed:{
keepAlivePages(){
return this.$store.state.keepAlivePages
}
},
created(){
}
}
</script>
这里用keep-alive对router-view进行 include动态缓存
Vuex
export default new Vuex.Store({
state: {
keepAlivePages: []
},
actions: {},
mutations: {
// 清空 缓存页面
CLEAR_KEEP_ALIVE_PAGES(state){
state.keepAlivePages = []
},
// push 一个缓存页面
PUSH_KEEP_ALIVE_PAGES(state, pageName){
if(state.keepAlivePages.includes(pageName)){
console.log('此页面已在缓存中')
} else {
state.keepAlivePages.push(pageName)
}
},
// 删除该缓存
REMOVE_KEEP_ALIVE_PAGES(state, pageName){
let index = state.keepAlivePages.findIndex((item) => {
return item === pageName
})
if(index !== -1) {
state.keepAlivePages.splice(index, 1)
} else {
console.log('该页面未被缓存')
}
}
},
getters: {}
});
这里对缓存的include 路由进行vuex 控制。提供push,remove,clear操作
Router.js 路由挂载配置
const router = new VueRouter({
mode: 'hash',
routes: [
{
path: '/',
name: 'PageHome',
meta:{
},
component: pageHome
},
{
path: '/form',
name: 'PageForm',
meta:{
keepAliveTo:['PageUser']
},
component: pageForm,
},
{
path: '/user',
name: 'PageUser',
meta:{
},
component: pageUser,
},
{
path: '/list',
name: 'PageList',
meta:{
keepAliveTo:['PageForm', 'PageDetail']
},
component: pageList,
},
{
path: '/detail',
name: 'PageDetail',
meta:{
},
component: pageDetail
}
]
})
export default router
可以看到,meta中记录了关键的keepAliveTo (去哪些页面需要缓存自身)
这些元信息在注册时我们就已经知道了。
with-keep-alive.js 控制缓存的mixin片段
export default {
methods: {
...mapMutations({
pushKeepAlivePage: 'PUSH_KEEP_ALIVE_PAGES',
removeKeepAlivePage: 'REMOVE_KEEP_ALIVE_PAGES',
}),
keepAliveHook() {
console.log('可以从写覆盖此钩子,在缓存该页面时被调用, 可以实现定位滚动条等功能...')
}
},
async beforeRouteLeave (to, from, next) {
if(from.meta.keepAliveTo.includes(to.name)){
this.keepAliveHook && this.keepAliveHook()
// this.pushKeepAlivePage(from.name)
this.$store.commit('PUSH_KEEP_ALIVE_PAGES', from.name)
} else {
// this.removeKeepAlivePage(from.name)
this.$store.commit('REMOVE_KEEP_ALIVE_PAGES', from.name)
}
await this.$nextTick()
next()
}
}
在beforeRouteLeave 钩子中对路由meta中的配置进行读取使用如果要去的页面是需要缓存自己的,就将自己添加到缓存中。否则移除自己。
注意: keepAliveHook 是在缓存动作中注入的钩子,你可以在自己的组件中去重写它(mixin策略) 用来记录滚动条或者其他相关的操作。
PageList.vue
<script>
import withKeepAliveMixin from '@/with-keep-alive.js'
export default {
name: 'PageList',
mixins: [
withKeepAliveMixin
],
props: {
},
methods: {
init () {},
addData(){
this.$router.push('/form')
}
}
}
</script>
PageForm.vue
<template>
<xb-scaffold>
<xb-appbar slot="appbar">
<div @click="$router.go(-1)" slot="left">
🔙
</div>
<div>
新建
</div>
</xb-appbar>
<div class="page-form">
<div class="form-item">
客户名称: <input v-model="name" type="text">
</div>
<div class="form-item">
客户备注: <input v-model="remaker" type="text">
</div>
<div class="form-item">
负责人: <input v-model="user" readonly type="text">
<button @click="addUser">选择</button>
</div>
</div>
</xb-scaffold>
</template>
<script>
import withKeepAliveMixin from '@/with-keep-alive.js'
export default {
name: 'PageForm',
components: {
},
filters: {
},
mixins: [
withKeepAliveMixin
],
props: {
},
data () {
return {
name:'',
remaker: '',
user:'',
}
},
methods: {
init () {},
addUser(){
this.$router.push('/user')
}
}
}
</script>
可以看到对这些需要缓存的页面并没有添加额外代码,仅仅只是混入了mixin就能实现缓存。
3.注意事项
1.这里要主要include是对包裹组件的名字进行特定缓存,如果发现页面未缓存的时候需要看看是否是自己的名字和include 中的不对应
2.记录滚动条的位置可以对 mixin 中执行的钩子进行(keepAliveHook)重写。
3.此方案不考虑循环keepalive