Vue简易实现前进刷新,后退缓存

352 阅读2分钟

原理

在 created 函数调用时将需要缓存的 VNode 节点保存在 this.cache 中/在 render(页面渲染) 时,如果 VNode 的 name 符合缓存条件(可以用 include 以及 exclude 控制),则会从 this.cache 中取出之前缓存的 VNode 实例进行渲染。

VNode:虚拟DOM,其实就是一个JS对象

生命周期函数

activated

在 keep-alive 组件激活时调用

该钩子函数在服务器端渲染期间不被调用

deactivated

在 keep-alive 组件停用时调用

该钩子在服务器端渲染期间不被调用

被包含在 keep-alive 中创建的组件,会多出两个生命周期的钩子: activated 与 deactivated

使用 keep-alive 会将数据保留在内存中,如果要在每次进入页面的时候获取最新的数据,需要在 activated 阶段获取数据,承担原来 created 钩子函数中获取数据的任务。

注意: 只有组件被 keep-alive 包裹时,这两个生命周期函数才会被调用,如果作为正常组件使用,是不会被调用的,以及在 2.1.0 版本之后,使用 exclude 排除之后,就算被包裹在 keep-alive 中,这两个钩子函数依然不会被调用!另外,在服务端渲染时,此钩子函数也不会被调用。

实现目的

假设有A,B,C三个页面, A > B > C 的流程下: 页面不缓存, C > B > A 的流程下: B页面进行缓存。

实现步骤

  1. 路由的配置:

router.js

    routes: [
        {
            path: '/',
            component: A,
            name: A
        },
        {
            path: '/b',
            component: B,
            name: B,
            meta: {
                keepAlive: true, // 需要被缓存
                isBack: false    // 用来判断是否后退
            }
        },
        {
            path: '/c',
            component: C,
            name: C
        }
    ]
    
    
    router.beforeEach((to, from, next) => {
      let list = ['B'] // 存放需要缓存页面路由的name值
      if (list.indexOf(to.name) > -1) {
        to.meta.keepAlive = true
      }
      next()
    })
    
  1. B页面(需要被缓存的页面)
     mounted () {
      this.getData()
    },
    activated() {
      if(!this.$route.meta.isBack) {
        // 如果isBack是false,表明需要获取新数据,否则就不再请求,直接使用缓存的数据
        this.getData()
      }
      // 恢复成默认的false,避免isBack一直是true,导致下次无法获取数据
      this.$route.meta.isBack = false
    },
    beforeRouteEnter(to, from, next) {
      //判断是从哪个路由过来的,若是C页面不需要刷新获取新数据,直接用之前缓存的数据即可
      if(from.name === 'C') {
        to.meta.isBack = true;
      }
      next();
    },
    beforeRouteLeave (to, from, next) {
      // 回到A页面,并销毁keep-live
      if (to.name === 'A' && this.$route.meta.isBack) {
        from.mate.keepAlive = false
        this.$destroy()
      }
      next()
    }