Vue2中 keep-alive 使用,如何清除 keep-alive 缓冲的组件

一、< keep-alive >

< keep-alive > 用来缓冲插槽中的内容(缓冲后不会重新渲染),就是 < keep-alive >……< / keep-alive>标签包裹的内容,里面只允许一个根标签,多个根标签只缓冲第一个标签,如:

<keep-alive>
	<div>root1</div>
	<p>root2</p>
	……
</keep-alive>

上面有多个根节点情况,< keep-alive > 只会缓冲第一个根节点。< keep-alive > 自身不会渲染一个 DOM 元素,也不会出现在组件的父组件链中。当在 < keep-alive >中切换缓冲过的组件时,会触发 activated 和 deactivated 这两个生命周期钩子函数。

注:<keep-alive>常包裹路由视图<router-view>或动态组件<component :is="">来使用

二、清除 < keep-alive > 缓冲的组件

清除缓冲有两种方案:1. 使用 < keep-alive > 标签提供的 include、exclude 属性;2. 操作 < keep-alive > 组件内部的缓冲数据 cache, keys

清除缓冲的场景:打开多个子页面,每个子页面切换时,保留每个子页面状态(缓冲),手动关闭后(清除缓冲),重新打开要新加载。如下图场景:
在这里插入图片描述

  1. include, exclude, max
    include:控制哪些组件能够缓冲,在其匹配值内的组件才能缓冲。
    exclude:控制哪些组件不能够缓冲,在其匹配值内的组件不能缓冲。
    include 和 exclude 可单独使用,也可同时使用,若同时使用有相同值时,则该组件不会被缓冲,因为 exclude 优先级高于 include
    max:最多可以缓存多少组件实例。一旦这个数字达到了,在新实例被创建之前,已缓存组件中最久没有被访问的实例会被销毁掉。
    include 和 exclude 允许组件有条件地缓存。二者都可以用逗号分隔字符串、正则表达式或一个数组来表示,无论哪种形式数据,其值都是针对组件名称,就是给组件命名的 name 值,也就是说使用这两个属性控制组件是否缓冲,组件必须要命名。常用数组作为这两个属性值,数组元素就是命名的组件名称。这两个属性使用实例:
<!-- 逗号分隔字符串 -->
<keep-alive include="a,b">
  <component :is="view"></component>
</keep-alive>

<!-- 正则表达式 (使用 `v-bind`) -->
<keep-alive :include="/a|b/">
  <component :is="view"></component>
</keep-alive>

<!-- 数组 (使用 `v-bind`) -->
<keep-alive :include="['a', 'b']">
  <component :is="view"></component>
</keep-alive>

清除缓冲: 操作 include 或者 exclude 都行,例如:可以给 include 绑定一个数组,该数组来自 Vuex 的 state,这样能够进行全局管理组件是否缓冲,数组初始值则为所有需要缓冲的组件名称列表清除缓冲时,只需要将不缓冲的组件名称从数组中移除即可(注:再次进入该组件之前,必须要将其名称加入到数组中,不然不会缓冲,因为你上一步把它从数组中移除了)。< keep-alive > 源码实现中有对应的 include 和 exclude 属性监听器,两者属性值变化时会动态处理 cache 和 keys 将哪些不需要缓冲的组件移除。

  1. cache, keys
    想弄明白操作 cache、keys 清除缓冲原理,需要了解 < keep-alive > 组件的源码实现,可阅读这篇文章< keep-alive >源码解读
    我这里可以和你们简单说下:< keep-alive > 内部将需要缓冲的组件都放在了 cache 对象里,缓冲的组件所绑定的key值会作为 cache 对象的键名,若组件未绑定key,内部会有一个生成键名的规则,该规则会结合组件实例 componentOptions 中的 cid 生成一个key 作为 cache 的键名(如下图控制台打印出来的虚拟DOM中的 cid)。cache 对象中键名对应的键值则为当前组件的虚拟DOM(里面的 elm 属性值存放的是组件DOM)。< keep-alive > 中的 keys 是一个列表,用来存放已经缓冲组件的 key,也就是 cache 的键名,keys 列表采用 LRU 算法进行更新维护,将最近最少使用的缓冲组件放在 keys 头部,最新使用的放在末尾。为什么还要多加一个 keys 存放缓冲组件key?主要是想缓冲组件达到一定数量时,或者使用 max 属性时,保证删除的是最近最少使用的组件,来释放空间。
    在这里插入图片描述
    清除缓存: 给 < keep-alive > 包裹的组件绑定 ref(假设 ref 值为 routerView),通过 this.$refs.routerView. $ vnode.parent.componentInstance 获取 < keep-alive > 的 VNode 中的组件实例 componentInstance 属性,在控制台打印出来如下图,可看到 cache, keys 属性,将这俩参数浅拷贝出来,为什么不直接给 < keep-alive > 绑定 ref 获取?因为尝试过获取不到。。。缓冲的组件必须要绑定 key ,因为不绑定 key ,< keep-alive > 内部帮我们生成的 key ,我们无法得知,就没办法手动根据 key 删除指定缓冲组件。我在项目里是用路由组件对应的路由地址作为 key,项目代码在文末。删除指定缓冲的组件时,通过组件 key ,删除 cache 的对应 key 属性,dom被删除,keys 列表也要同步更新,删除对应 key。
    在这里插入图片描述
<template>
  <transition name="fade-transform" mode="out-in">
    <keep-alive>
      <router-view ref="routerView" :key="$route.path" />
    </keep-alive>
  </transition>
</template>

<script>
import { $bus } from '@utils/eventBus.js'
export default {
  data() {
    return {
      cachePage: [],
    }
  },
  mounted() {
    this.$nextTick(() => {
      // 打印的keep-alive组件实例在上图
      console.log(this.$refs.routerView.$vnode.parent.componentInstance)
      $bus.$on('removeCachePage', key => {
        /**
         * @param {Object} cache:类数组对象,存放缓冲的路由组件,键值对形,key为路由路径,value为路由组件Vnode
         * @param {Array} keys:数组,存放缓冲的路由组件的key,即路由路径
         * @param {String} key:字符串,路由组件的key,指定要删除的路由组件key值
         */
        const { cache, keys } = this.$refs.routerView.$vnode.parent.componentInstance
        Object.prototype.hasOwnProperty.call(cache, key) &&
          (() => {
            // 点击tab关闭页面,移除对应页面缓冲
            delete cache[key]
            keys.splice(keys.indexOf(key), 1)
            console.log('%c 删除缓冲页面成功!', 'color:red')
          })()
      })
    })
  },
  beforeDestroy() {
    $bus.$off('removeCachePage')
  },
}
</script>

<style scoped lang="less"></style>

  • 8
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
Vue2 ,你可以使用 `keep-alive` 组件来缓存指定的路由组件。`keep-alive` 组件可以缓存被包裹的组件的状态,以避免每次切换到该组件时都重新渲染。 要缓存指定的路由组件,你需要在路由配置给该路由组件添加 `meta` 字段,然后在 `keep-alive` 组件使用 `include` 或 `exclude` 属性来指定需要缓存的路由组件。具体实现步骤如下: 1. 在路由配置给需要缓存的路由组件添加 `meta` 字段,例如: ```javascript const routes = [ { path: '/home', component: Home, meta: { keepAlive: true // 需要缓存该组件 } }, { path: '/about', component: About } ] ``` 2. 在使用 `keep-alive` 组件的父组件使用 `include` 或 `exclude` 属性来指定需要缓存的路由组件,例如: ```html <template> <div> <router-view v-slot="{ Component }"> <keep-alive :include="cachedViews"> <component :is="Component" /> </keep-alive> </router-view> </div> </template> <script> export default { computed: { cachedViews() { // 获取需要缓存的路由组件 return this.$route.matched.filter(route => route.meta.keepAlive).map(route => route.component) } } } </script> ``` 在上面的例子,`cachedViews` 计算属性返回了所有需要缓存的路由组件,然后在 `keep-alive` 组件使用了 `include` 属性来指定需要缓存的路由组件。 如果你想排除某些路由组件,可以使用 `exclude` 属性来指定不需要缓存的路由组件

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值