【Vue3第二十二章】KeepAlive缓存组件

前言

在Vue后台管理项目开发过程中,·有时候会采用类似选项卡的方式,将左侧菜单至于顶部,便于快捷访问。
在这里插入图片描述

而问题是,每访问一次组件,都会重新创建一个新的vue组件实例,切换组件的时候会把其他访问过的组件的网络请求全部重新发一遍。也就是会重头执行一遍created,mounted,destroy等一个完整的vue生命周期,并且数据全部都会初始化。
这样虽好,能保持永远是最新的数据,但是很多业务场景下,我们并不想有这样的效果。再举个例子:
现在有一个表单页面,我填写表单的同时,可能需要回去上一级页面查看一些信息来填入表单,你按照使用的惯例通过路由回到上一页,当你查看完上级组件的信息在切回表单界面会发现,表单信息全部都没了这样就显得很不友好了。接下来,需要一些手段保留组件的状态,那就是keep-alive的作用啦。
使用keep-alive的好处就是,在组件切换过程中将状态保留在内存中,防止重复渲染DOM,减少加载时间及性能消耗,提高用户体验性。

数字化管理平台
Vue3+Vite+VueRouter+Pinia+Axios+ElementPlus
权限系统-商城
个人博客地址

一、基本用法

1.1 概述

有时候我们不希望组件被重新渲染影响使用体验;或者处于性能考虑,避免多次重复渲染降低性能。而是希望组件可以缓存下来,维持当前的状态。这时候就需要用到 <KeepAlive> 组件。

开启<KeepAlive>生命周期的变化

  • 初次进入时: onMounted> onActivated
  • 退出后触发 deactivated
  • 再次进入:只会触发 onActivated

1.2 代码演示

<script setup>
    import { ref,shallowRef } from 'vue'
    import CompA from './CompA.vue'
    import CompB from './CompB.vue'

    const current = shallowRef(CompA)
    
    let num = ref(10);
</script>

<template>
  <div class="demo">
    <label><input type="radio" v-model="current" :value="CompA" /> A</label>
    <label><input type="radio" v-model="current" :value="CompB" /> B</label>
  
    <KeepAlive>
    	<!-- 动态组件绑定 is 属性切换 -->
    	<component :is="current"></component>
    </KeepAlive>  
    
    <keep-alive>
    	<!-- 多个条件判断的子组件 -->
        <comp-a v-if="num > 1"></comp-a>
        <comp-b v-else></comp-b>
    </keep-alive>
    
    <!-- 和 Transition 动画组件一起使用 -->
    <transition>
        <keep-alive>
        	<component :is="current"></component>
        </keep-alive>
    </transition>
  </div>
</template>

事件挂载的方法等,只执行一次的放在 onMounted中;组件每次进去执行的方法放在 onActivated中

二、include包含 / exclude排除

2.1 概述

<KeepAlive> 默认会缓存内部的所有组件实例,但我们可以通过 includeexclude prop 来定制该行为。

  • include:包含,包含在这个集合或者用正则匹配到的name值的组件会被缓存
  • exclude:排查 包含在这个集合或者用正则匹配到的name值的组件不会被缓存

这两个 prop 的值都可以是一个以英文逗号分隔的字符串、一个正则表达式,或是包含这两种类型的一个数组

2.2 代码示例

<!-- 以英文逗号分隔的字符串 -->
<KeepAlive include="a,b">
  <component :is="view" />
</KeepAlive>

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

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

include和exclude会根据匹配的值返回一个布尔值,当然这个布尔值不是你来操控,而是keep-alive组件内部操作的,它会根据你传入的组件name来决定是这个布尔值如何体现,就是简单需要缓存和不需要缓存的区别。

三、max最大缓存实例数

可以通过传入 max prop 来限制可被缓存的最大组件实例数。<KeepAlive> 的行为在指定了 max 后类似一个 LRU 缓存:如果缓存的实例数量即将超过指定的那个最大数量,则最久没有被访问的缓存实例将被销毁,以便为新的实例腾出空间。

<KeepAlive :max="10">
  <component :is="activeComponent" />
</KeepAlive>

这里值得注意的是,设置了最大缓存组件上限的时候,会形成一个堆的数据结构的含义。当你设置的需要缓存的组件数量超过了max的限制,那么就会移除堆底的的元素,简而言之就是按照先进先出的规则操作。当到达缓存组件上限之后会移除最先缓存的第一个组件,并把新的缓存组件推入堆顶。

四、缓存实例的生命周期

当一个组件实例从 DOM 上移除但因为被 <KeepAlive> 缓存而仍作为组件树的一部分时,它将变为不活跃状态而不是被卸载。当一个组件实例作为缓存树的一部分插入到 DOM 中时,它将重新被激活

一个持续存在的组件可以通过 onActivated()onDeactivated() 注册相应的两个状态的生命周期钩子。

<script setup>
    import { onActivated, onDeactivated } from 'vue'

    onActivated(() => {
      // 调用时机为首次挂载
      // 以及每次从缓存中被重新插入时
    })

    onDeactivated(() => {
      // 在从 DOM 上移除、进入缓存
      // 以及组件卸载时调用
    })
</script>

onActivated 在组件挂载时也会调用,并且 onDeactivated 在组件卸载时也会调用。这两个钩子不仅适用于 <KeepAlive> 缓存的根组件,也适用于缓存树中的后代组件。

五、总结

被keep-alive包裹的组件,会被保留在组件树里,你可以继续操作其他叶子节点的组件,但是其他叶子节点的组件还会正常经历创建,生成,销毁的完整的声明周期,你重新访问组件的时候什么都是新的了,而这个被keep-alive包裹的组件就一直长在树上了,会一直存在,除了会经历创建生成,在页面卸载之前不会被销毁,你可以浅薄的理解为,像闭包一样保存在内存中不会消亡。在Vue中,就体现为,始终将该组件保留在虚拟DOM中,并且保持该组件以及后代组件的状态,只不过不渲染而已了,这里敲下黑板,注意一下,是始终将该组件保留在虚拟DOM中,并且保持该组件以及后代组件的状态但是不渲染了。嗯,没错,你引入的组件的后代组件也会被缓存的。

猜你喜欢

转载自blog.csdn.net/qq_39335404/article/details/129250171
今日推荐