vue移动端H5跨页面,缓存方案

2,522 阅读1分钟

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

4.效果展示