Problems with SPA applications

Let’s look at an example:

  1. Product listings are searched by brand

  1. Click the details button to enter the product details page

  2. Click the back button of the details page, and the search item disappears, redisplaying all products

In SPA applications we rarely open a new window, so there is a problem that the page returns with the same state as the previous page

Solution Keep-alive

Keep alive is introduced

Is an abstract component: it does not render a DOM element on its own, nor does it appear in the component’s parent chain.

When dynamic components are wrapped, inactive component instances are cached rather than destroyed.

Parameters received by keep-alive:

Include – a string or regular expression. Only components with matching names are cached.

Exclude – a string or regular expression. Any component with a matching name will not be cached.

Max – Numbers. Maximum number of component instances can be cached.

For more information about keep-alive, please refer to cn.vuejs.org/v2/api/#kee…

Keep alive – use

Common solutions on the network (problematic)

App.vue

<keep-alive>
    <router-view v-if="$route.meta.keepAlive"></router-view>
</keep-alive>
<router-view v-if=! ""$route.meta.keepAlive"></router-view>
Copy the code

keeplist.vue

beforeRouteLeave (to, from, next) {
    from.meta.keepAlive = to.name === 'keepdetail'
    next()
}
Copy the code

router.js

{
    path: 'keeplist',
    name: 'keeplist',
    meta: {
        keepAlive: true
    },
    component: () => import('./views/keeplist')}Copy the code

Question:

The first operation home–> keeplist–> keepDetail is ideal, but the second operation returns home–> keeplist–> KeepDetail –> keeplist, the cached data is still there. The following figure

Analysis:

The first time you enter the Keeplist page, the default is meta. KeepAlive = true

<keep-alive>
    <router-view v-if="$route.meta.keepAlive"></router-view>
</keep-alive>
Copy the code

When keeplist returns to home, the to.name! KeepAlive = ‘keepdetail’, so meta. KeepAlive is set to false, and the next time you enter the Keeplist page, you go

<router-view v-if=! ""$route.meta.keepAlive"></router-view>
Copy the code

When keeplist jumps to keepdetail, meta. KeepAlive is set to true, and when keeplist is returned from keepdetail, it goes

<keep-alive>
    <router-view v-if="$route.meta.keepAlive"></router-view>
</keep-alive>
Copy the code

This invokes the same cached page, so there is a problem with the second return

Use scheme (implementation Scheme) from keep-alive property value

Keep-alive contains two attributes: include and exclude

Include and exclude attributes allow components to cache conditionally. Both can be represented as comma-delimited strings, regular expressions, or an array.

The official sample

<! -- comma-separated string --> <keep-alive include="a,b">
  <component :is="view"></component> </keep-alive> <! -- regular expression (using 'v-bind') --> <keep-alive :include="/a|b/">
  <component :is="view"></component> </keep-alive> <! -- array (using 'v-bind') --> <keep-alive :include="['a', 'b']">
  <component :is="view"></component>
</keep-alive>
Copy the code
  1. Manage include and exclude in VUex
exportdefault new Vuex.Store({ state: { keepInclude: [], keepExclude: [] }, mutations: {[ADD_KEEP_INCLUDE] (state, payload) {// TODO add cache name state.keepinclude = state.keepinclude. filter(item => item! == payload) state.keepInclude.push(payload) console.log(state.keepInclude) }, [REMOVE_KEEP_INCLUDE] (state, KeepInclude = state.keepinclude. filter(item => item! == payload) }, [ADD_KEEP_EXCLUDE] (state, KeepExclude = state.keepexclude. Filter (item => item! == payload) state.keepExclude.push(payload) }, [REMOVE_KEEP_EXCLUDE] (state, KeepExclude = state.keepexclude. Filter (item => item! == payload) } } })Copy the code
  1. Define two methods for easy use in components
import store from '@/store'

const newCache = function (routerName) {
  store.commit('ADD_KEEP_INCLUDE', routerName)
  store.commit('REMOVE_KEEP_EXCLUDE', routerName)
}
const clearCache = function (routerName) {
  store.commit('ADD_KEEP_EXCLUDE', routerName)
  store.commit('REMOVE_KEEP_INCLUDE', routerName)
}
export {
  clearCache, newCache
}
Copy the code
  1. Cooperate with beforeRouteEnter and beforeRouteLeave to achieve data caching
import { clearCache, newCache } from '@/common/index'
export default {
  name: 'keepa',
  beforeRouteEnter (to, from, next) {
    newCache('keepa')
    next()
  },
  beforeRouteLeave (to, from, next) {
    if (to.name.indexOf('home') > -1) {
      clearCache('keepa')
    }
    next()
  }
}
Copy the code
  1. Add the keep-alive component outside the routing page
<keep-alive :include="keepInclude" :exclude="keepExclude">
    <router-view :key="$route.fullPath"/>
</keep-alive>
Copy the code

Important Notes

  1. The component names in include and exclude are the value of name in the single-file component, not the router name
  2. It is recommended to use an array for include and exclude. If include and exclude are empty, they are cached by default. Components are incorrectly cached
  3. Exclude takes precedence over include. If a component exists in both include and exclude, it will not be cached