Vue mobile H5 cross-page, caching scheme

1. The scene

I believe that you will need to cross pages more or less when developing mobile terminals (see details, fill in the form….) This demand.

This is where cross-routing becomes a headache. Here’s a solution

2. Implementation idea

First of all, it is based on 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>
Copy the code

Keep-alive is used to cache the router-view dynamically

Vuex

export default new Vuex.Store({
  state: {
    keepAlivePages: []},actions: {},
  mutations: {
    // Clear the cached page
    CLEAR_KEEP_ALIVE_PAGES(state){
      state.keepAlivePages = []
    },
    // push a cached page
    PUSH_KEEP_ALIVE_PAGES(state, pageName){
      if(state.keepAlivePages.includes(pageName)){
        console.log('This page is already in cache')}else {
        state.keepAlivePages.push(pageName)
      }
    },
    // Delete the cache
    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('This page is not cached')}}},getters: {}});Copy the code

Vuex control is performed on cached include routes. Provides push, remove, and clear operations

Router.js Routing mount configuration

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
Copy the code

As you can see, the key keepAliveTo is recorded in the meta (which pages need to cache themselves)

This meta information is already known at the time of registration.

With-keep-alive. js controls cached mixin fragments

export default {
  methods: {
    ...mapMutations({
      pushKeepAlivePage: 'PUSH_KEEP_ALIVE_PAGES'.removeKeepAlivePage: 'REMOVE_KEEP_ALIVE_PAGES',}).keepAliveHook() {
      console.log('can override this hook from write, can be called when caching the page, can implement scrollbar positioning, etc... ')}},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()
  }
}
Copy the code

The beforeRouteLeave hook is used to read the configuration in the routing meta. If you want to go to a page that needs to cache itself, add itself to the cache. Otherwise remove yourself.

Note: keepAliveHook is a hook that is injected into the cache action and you can override it in your own component to record scroll bars or other related operations.

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>
Copy the code

PageForm.vue

<template> < xB-scaffold > < xB-appbar slot="appbar"> <div @click="$router.go(-1)" slot="left"> 🔙 </div> <div> New </div> </xb-appbar> <div class="page-form"> <div class="form "> <input V-model ="name" type="text"> <input v-model="remaker" type="text"> <input V-model ="user" readonly type="text"> < button@click ="addUser"> </button> </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>Copy the code

As you can see, there is no additional code for these pages that need to be cached, just mixins to cache them.

3. Precautions

1. Here the main include is to cache the name of the package component. If you find that the page is not cached, you need to check whether your name does not correspond to the name in the include

2. Record the position of the scroll bar. Keep alivehooks executed in mixins can be overwritten.

3. Loop Keepalive is not considered in this scheme

4. Effect display