VUE清除keepalive页面缓存

需求说明:

本文章主要是解决第三个需求。

代码如下: 

(代码说明:store.state.pages是我存储标签页的列表,记录了当前打开的标签页的路由数据)

旧的方法:

// 使用Vue.mixin的方法拦截了路由离开事件,并在该拦截方法中实现了销毁页面缓存的功能。
let cachePageDataList = []
Vue.mixin({
  beforeRouteLeave: function (to, from, next) {
    const pages = this.$store.getters.pages.map(item => {
      return item.name
    })
    const expect = ['login']
    if (from && expect.indexOf(from.name) < 0 && pages.indexOf(from.name) < 0) { // 此处判断该路由对应的标签页是否已关闭,以此判断是否摧毁本层缓存。
      const $vnode = this.$vnode
      if (($vnode && $vnode.data.keepAlive) &&
          ($vnode.parent && $vnode.parent.componentInstance && $vnode.parent.componentInstance.cache) &&
          ($vnode.componentOptions)
      ) {
        var key = $vnode.key == null ? $vnode.componentOptions.Ctor.cid + ($vnode.componentOptions.tag ? `::${$vnode.componentOptions.tag}` : '') : $vnode.key
        var cache = $vnode.parent.componentInstance.cache
        var keys = $vnode.parent.componentInstance.keys
        if (cache[key]) {
          if (keys.length && keys.indexOf(key) > -1) {
            keys.splice(keys.indexOf(key), 1)
          }
          delete cache[key]
        }
      }
      // this.$destroy()
    }
    next()
  },
  watch: {
    '$store.getters.pages': function (v) {
      const temp = [...cachePageDataList]
      const c = v.map(item => {
        return item.name
      })
      if (c.join(',') !== temp.join(',')) {
        cachePageDataList = [...c]
        // 判断是否有页面被删除了
        temp.forEach(item => {
          if (c.indexOf(item) < 0) { // 这个标签页被关闭了
            console.log('%c 222222222222222222222', 'color:red;font-size:20px')
            console.log(item + '被关闭了,当前路由是:' + this.$route.name)
            const current = this.$route
            if (item !== current) {
              this.$router.push({ name: item }) // 跳转一下这个被删除的标签页,然后再调回当前页,以此来触发beforeLeave事件
              this.$router.push(current)
            }
          }
        })
      }
    }
  }
})

旧方法的思路步骤是:

1、每次监听到路由离开事件时,判断是否需要清除该页面的缓存,如果是,则清除;

2、监听【标签页】的变化,如果有标签页被关闭了,就打开该页面路由、再关闭,从而手动触发路由离开事件

旧方法的核心是拦截路由离开事件,但是这种方法有缺陷是:

缺陷1、步骤2时会导致额外的路由跳转,如果该路由下的页面比较复杂,会导致额外的性能消耗;

缺陷2:当同时关闭多个页面缓存时,可能导致长时间的卡顿;

由此作出一些改进。。。

------------ 分割线 -------------

新的方式:

// 使用Vue.mixin的方法存储页面缓存,并且当标签页关闭时,清除页面缓存
let cachePageDataList = []
let cacheList, keysList
const nameKeyList = {}
Vue.mixin({
  beforeRouteEnter (to, from, next) {
    next(vm => {
      // console.log('%c 进入页面' + to.name, 'color:red;font-size:20px')
      const $vnode = vm.$vnode
      if (($vnode && $vnode.data.keepAlive) &&
        ($vnode.parent && $vnode.parent.componentInstance && $vnode.parent.componentInstance.cache) &&
        ($vnode.key || $vnode.componentOptions)
      ) {
        var key = $vnode.key == null ? $vnode.componentOptions.Ctor.cid + ($vnode.componentOptions.tag ? `::${$vnode.componentOptions.tag}` : '') : $vnode.key
        var cache = $vnode.parent.componentInstance.cache
        var keys = $vnode.parent.componentInstance.keys
        if (!cacheList) cacheList = cache
        if (!keysList) keysList = keys
        nameKeyList[to.name] = key
        // console.log(cacheList, keysList, nameKeyList)
      }
    })
  },
  watch: {
    '$store.getters.pages': function (v) {
      const temp = [...cachePageDataList]
      const newpages = v.map(item => {
        return item.name
      })
      if (newpages.join(',') !== temp.join(',')) {
        cachePageDataList = [...newpages]
        // 判断是否有页面被删除了
        temp.forEach(item => {
          if (newpages.indexOf(item) < 0) { // 监听到这个标签页被关闭了
            // console.log('%c 这个标签页被关闭了:' + item, 'color:red;font-size:20px')
            // console.log(item + '被关闭了,当前路由是:' + this.$route.name)
            // 删除缓存的核心方法 start
            const key = nameKeyList[item]
            if (key && cacheList[key]) {
              if (keysList.length && keysList.indexOf(key) > -1) {
                keysList.splice(keysList.indexOf(key), 1)
              }
              delete cacheList[key]
            }
            // 删除缓存的核心方法 end
          }
        })
      }
    }
  }
})

新方式的思路步骤是:

1、首次任意路由时,把cacheList和keysList的指针保存起来,备用

2、每次进入路由时,将该页面的路由name和组件key保存起来,备用

3、监听到该路由页面标签关闭时,使用cacheList和keysList删除页面缓存

这里面的核心方法是如何删除页面缓存、怎么获取页面组件key?(见代码)

新方式的思路导图:

由此,可以解决卡顿的问题,提高性能。

原文地址:https://www.cnblogs.com/mankii/p/13746051.html