• 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?(见代码)

    新方式的思路导图:

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

  • 相关阅读:
    HDU 1421 DP
    HDU1011 树形DP
    CodeForces 219D 树形DP
    HDU2196 树形DP
    HDU5831
    HDU3177 贪心
    数位DP HDU3652
    数位DP bzoj1026
    数位DP HDU3555
    数位DP HDU2089
  • 原文地址:https://www.cnblogs.com/mankii/p/13746051.html
Copyright © 2020-2023  润新知