There is always a way, it depends on whether you want to go astray.

scenario

In A recent development, three pages A, B and C were designed. Imagine A scenario requirement like this:

  • Leave page B to page C and cache data from page B (keepAlive: true)
  • Leave page B and enter page A without caching page B data (keepAlive: false)

concept

  • keep-alive

    • When keep-alive wraps dynamic components, it caches inactive component instances rather than destroying them. Like Transition, keep-Alive is an abstract component: it doesn’t render a DOM element on its own, and it doesn’t appear in the parent component chain.
    • Keep alive: vue document
  • Guard within component – beforeRouteLeave

    • Called when navigating away from the component’s corresponding route
    • Component instances can be accessedthis
    • Guard within component: Vue-router document

Front background: Keep-alive component implementation

  • Add specific fields, such as keepAlive, to the route meta information
  const router = new VueRouter({
  routes: [{path: '/foo'.component: Foo,
      children: [{path: 'bar'.component: Bar,
          // a meta field
          meta: { 
            keepAlive: true}}]}})Copy the code
  • The parent component dynamically uses the keep-alive tag based on the keepAlive field in the route
  class Home extends Vue {

    get keepAlive () {
      // Get the keepAlive field in the metinformation of the current route
      return this.$route.meta.keepAlive
    }

    private render () {
      return( <div> { ! this.keepAlive && <router-view /> } <keep-alive> { this.keepAlive && <router-view/> } </keep-alive> </div> ) } } export default HomeCopy the code

Train of thought

The keep-alive of a component is dynamically used based on the keepAlive field in the routing element. Therefore, dynamic cache can be realized by dynamically changing the keepAlive field of the corresponding routing element.

Implementation scheme

Plan a

  • Use beforeRouteLeave to change keepAlive implementation from
beforeRouteLeave (to: any, from: any, next: any) {
  // called when navigating away from the component's corresponding route
  // Check if you are going to page C
  if(to.name ! = ='C') {
    // Do not go to C page, do not cache
    from.meta.keepAlive = false
  } else {
    // Go to the C page, cache
    from.meta.keepAlive = true
  }
  next()
}
Copy the code

Bug: When I go to page C for the first time and return to page B, page B is not cached. When I go to page C for the second time, page B is cached, and entering page A does not clear the cache of page B

Scheme 2 (Network Scheme)

  • Destroyed $destroy ()
beforeRouteLeave (to: any, from: any, next: any) {
  // called when navigating away from the component's corresponding route
  // Check if you are going to page C
  if(to.name ! = ='C') {
    // Do not go to C page, do not cache
    this.$destroy()
  }
  next()
}
Copy the code

Bug: Destruction is never cached

Scheme 3 (Network Scheme)

  • Cached components have a cache property that can be forcibly removed by code. The disadvantage is that it still takes up memory
  • Concrete implementation reference

Scheme 4 (Optimal solution)

  • Using keep-alive include attribute, vuEX dynamic control include to achieve dynamic management cache
  • I won’t go into details here, there are many examples of relevant code on the Internet, and the principle is very simple

This solution is available in special scenarios where the preceding solutions cannot be implemented

Special scenario

  • This project is a mobile terminal project, and the include attribute of keep-alive is not used. If it is added, many configurations of the project need to be modified, which is quite troublesome

The solution

  • The solution is similar to solution 1 above
  • The difference between:
    • Change keepAlive without manipulating the from object in beforeRouteLeave
    • Run keepAlive on this.$router
// Operates on the meta information of the route specified by name
private changeKeepAlive (parentName: string, name: string, keepAlive: boolean) {
  // @ts-ignore
  this.$router.options.routes.map((item: any) = > {
    if (item.name === parentName) {
      item.children.map((a: any) = > {
        if (a.name === name) {
          a.meta.keepAlive = keepAlive
        }
      })
    }
  })
}

beforeRouteLeave (to: any, from: any, next: any) {
    // called when navigating away from the component's corresponding route
    // Access component instance 'this'
    if (to.name === 'C') {
      this.changeKeepAlive('Home'.'B'.true)}else {
      this.changeKeepAlive('Home'.'B'.false)
    }
    next()
  }
Copy the code

When tested, this solution does not have the bug of plan 1

BY – LucaLJX (LucaLJX lot)