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?(見代碼)

新方式的思路導圖:

由此,可以解決卡頓的問題,提高性能。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM