前端开发那些事儿

vue keep-alive缓存问题

2020-09-28  本文已影响0人  无疆wj

场景:
list页面(要缓存),跳转到details页面,
需求:
1 从details页面返回后 list页面不刷新,并保持离开时的位置.
2 从其他任意页面进入list页面,正常刷新

方案:
1 使用keep-alive包裹router-view

<div id="app">
        <keep-alive>
            <router-view v-if="$route.meta.keepAlive"></router-view>
        </keep-alive>

        <!-- 这里不会被keepalive -->
        <router-view v-if="!$route.meta.keepAlive"></router-view>
</div>

2 路由注册,添加meta

 {
      path: '/list',
      name: 'List',
      component: () => import('@/pages/list.vue'),
      meta: {
        keepAlive: true
      }
},

3 list.vue中使用beforeRouteLeave钩子

beforeRouteLeave(to, from, next) {
        if (to.name == "details") {
            from.meta.keepAlive = true
        } else {
            from.meta.keepAlive = false
        }
        next()
},

4 在组件中记录scroll滑动的距离

this.scrollTop = document.querySelector(  ".scroll-box"  ).scrollTop

keep-alive缓存组件重新激活时会触发activated周期函数,在此函数中做滚动,回到跳转details.vue前的位置

activated() {
       document.querySelector(".scroll-box").scrollTop = this.scrollTop 
},

问题:
list页面会由于数据的不同,重复缓存,details返回后的页面不是它的真正的上级页面
场景还原:
点击/list?id=01 下的01-item 前往01-item-details,返回后为/list?id=01下的页面,正常
再点击/list?id=02 下的02-item 前往02-item-details,返回后仍为/list?id=01下的页面,异常
原因:第二次返回list?id=02时返回的是keep-alive已缓存的组件(即第一次缓存的list组件)

解决问题:
手动销毁已缓存的list组件,使其每次进入list都重新缓存新的页面;
1 使用keep-aliveexclude属性(任何名称匹配的组件都不会被缓存)

<keep-alive :exclude="exclude" >
      <router-view v-if="$route.meta.keepAlive"></router-view>
</keep-alive>
data() {
    return {
      exclude: this.$exclude,
    }
  },

2 对list.vue中的beforeRouteLeave钩子函数做修改

beforeRouteLeave(to, from, next) {
        // 离开list页面且进入的不是details页面
        if (to.name != "details") {
          // exclude添加匹配后,会自动销毁已缓存的组件
            this.$exclude.push(this.$options.name) 
          // 缓存组件销毁后要把exclude中的匹配删除,不然下次进去页面不会缓存当前组件
            setTimeout(() => {
                for (let i = 0; i < this.$exclude.length; i++) {
                    if (this.$exclude[i] == this.$options.name) {
                        this.$exclude.splice(i, 1)
                        break
                    }
                }
            }, 0)
        }
        next()
    },
上一篇下一篇

猜你喜欢

热点阅读