011-keep-alive详解

keep-alive详解

1、简介

  • keep-alive 是 Vue 的内置组件,当它包裹动态组件时,会缓存不活动的组件实例,而不是销毁它们。
  • 原理: 在 created 函数调用时将需要缓存的 VNode 节点保存在 this.cache 中,在 render(页面渲染) 时,如果 VNode 的 name 符合缓存条件(可以用 include 以及 exclude 控制),则会从 this.cache 中取出之前缓存的 VNode 实例进行渲染。

2、keep-alive的使用效果

demo分为上面的路由导航部分,下面的内容区部分。点击上面的路由导航,路由视图渲染对应的路由组件。效果图如下:

未使用keep-alive的效果图

对应代码

html 复制代码
// #App.vue中
<template>
  <div class="box">
    <!-- 路由导航 -->
    <div class="nav">
      <router-link to="/">去home页面</router-link>
      <router-link to="/about">去about页面</router-link>
      <router-link to="/detail">去detail页面</router-link>
    </div>
    <!-- 路由导航对应的内容区 -->
    <main>
      <router-view></router-view>
    </main>
  </div>
</template>
 
// home.vue中,放置一个复选框
<el-checkbox v-model="checked">备选项</el-checkbox>
 
// about.vue中,放置一个输入框
<el-input v-model="input" placeholder="请输入内容"></el-input>
 
// detail.vue中方式一个下拉框
<el-select v-model="value" placeholder="请选择">
  <el-option
    v-for="item in options"
    :key="item.value"
    :label="item.label"
    :value="item.value"
  >
  </el-option>
</el-select>

分析:

我们发现,当我们没有使用keep-alive组件包裹住router-view视图组件的时候,左边~我们在去home页面勾选了,在去about页面输入了,在去detail页面下拉选择了,离开这个路由页面,再回来时,我们发现我们之前做的操作,勾选、输入、下拉选择都不存在了,之前的状态都没了。原因很简单,当离开这个路由页面的时候,会触发这个路由页面对应组件上的destroy钩子方法,然后这个路由页面对应的组件就被销毁了,组件销毁了,组件上的挂载的数据也就啥也没有了。

使用keep-alive的效果图

对应代码

html 复制代码
<template>
  <div class="box">
    <!-- 路由导航 -->
    <div class="nav">
      <router-link to="/">去home页面</router-link>
      <router-link to="/about">去about页面</router-link>
      <router-link to="/detail">去detail页面</router-link>
    </div>
    <!-- 路由导航对应的内容区 -->
    <main>
      <keep-alive> <!-- 使用keep-alive包了一层,就可以缓存啦 -->
        <router-view></router-view>
      </keep-alive>
    </main>
  </div>
</template>

分析:

我们给视图层组件使用keep-alive包住以后,我们发现,我们勾选、输入、下拉选择的内容,在路由来回切换的时候,就不会丢失了,即使用keep-alive保存了之前的组件状态。

引出问题:

看到这里我们发现,直接加上keep-alive的话,会把所有的router-view层级下的视图的组件都缓存了,不过有的时候,我们只想缓存部分,不想缓存所有的,那这怎么办呢?没关系,大佬们已考虑到了,已经提前为我们解决好了,就是keep-alive中的include、exclude属性。

include和exclude指定是否缓存某些组件

参数名 描述
include 字符串或正则表达式 名称匹配的组件会被缓存
exclude 字符串或正则表达式 名称匹配的组件不会被缓存
max 数字 最多可以缓存多少组件实例

💡 Tips:include/exclude 值是组件中的 name 命名,而不是路由中的组件 name 命名

html 复制代码
// 指定home组件和about组件被缓存
<keep-alive include="home,about" >
    <router-view></router-view>
</keep-alive>

// 除了home组件和about组件别的都缓存,本例中就是只缓存detail组件
<keep-alive exclude="home,about" >
    <router-view></router-view>
</keep-alive>

引出问题:

我们知道组件中都有对应的逻辑js部分,而且组件要发请求获取数据的,一般情况下,我们都是在created或者mounted钩子中去发请求,向后端的大佬要数据的,关于使用keep-alive后的组件的钩子函数的问题,我们需要注意一下

使用keep-alive的钩子函数执行顺序问题

首先使用了keep-alive的组件以后,组件上就会自动加上了activated钩子和deactivated钩子。

  • activated 当组件被激活(使用)的时候触发 可以简单理解为进入这个页面的时候触发
  • deactivated 当组件不被使用(inactive状态)的时候触发 可以简单理解为离开这个页面的时候触发

假设我们只缓存home组件,我们先看一下代码,再在钩子中打印出对应的顺序。就知道钩子执行的顺序了:

html 复制代码
<template>
  <div>
    <el-checkbox v-model="checked">备选项</el-checkbox>
  </div>
</template>
<script>
export default {
  name: "home",
  data() { return { checked: false } },
  created() {
    console.log("我是created钩子");
  },
  mounted() {
    console.log("我是mounted钩子");
  },
  activated() {
    console.log("我是activated钩子");
  },
  deactivated() {
    console.log("我是deactivated钩子");
  },
  beforeDestroy() {
    console.log("我是beforeDestroy钩子");
  },
};
</script>

我们来回切换 看控制台打印顺序,得出结论如下:

  • 初始进入和离开 created --> mounted --> activated --> deactivated
  • 后续进入和离开 activated --> deactivated

所以我们可以在activated 和deactivated钩子中去做一些逻辑处理,这两个钩子有点类似mounted和beforeDestroy钩子,但是还是不一样。毕竟使用keep-alive不会销毁组件

3、keep-alive的应用场景举例

  • 查看表格某条数据详情页,返回还是之前的状态,比如还是之前的筛选结果,还是之前的页数等
  • 填写的表单的内容路由跳转返回还在,比如input框、下选择拉框、开关切换等用户输入了一大把东西,跳转再回来不能清空啊,不能让用户再写一遍啊,是吧老铁
  • 反正就是保留之前的状态,具体应用场景其实也有很多,在此不赘述...

4、总结

  1. 用于保留组件状态或避免重新渲染,包裹动态组件时,会缓存不活动的组件实例,而不是销毁它们。
  2. 当组件在 keep-alive内被切换,它的 activated 和 deactivated 这两个生命周期钩子函数将会被对应执行。
  3. 页面第一次进入时,生命周期触发:created-mounted-activated,后续进入和离开 activated --> deactivated。
  4. <keep-alive includ="xxx"> <router-view /> </keep-alive> 指定部分 name 为 xxx 的组件会被缓存。
相关推荐
y先森3 小时前
CSS3中的伸缩盒模型(弹性盒子、弹性布局)之伸缩容器、伸缩项目、主轴方向、主轴换行方式、复合属性flex-flow
前端·css·css3
前端Hardy3 小时前
纯HTML&CSS实现3D旋转地球
前端·javascript·css·3d·html
susu10830189113 小时前
vue3中父div设置display flex,2个子div重叠
前端·javascript·vue.js
IT女孩儿4 小时前
CSS查缺补漏(补充上一条)
前端·css
吃杠碰小鸡5 小时前
commitlint校验git提交信息
前端
虾球xz6 小时前
游戏引擎学习第20天
前端·学习·游戏引擎
我爱李星璇6 小时前
HTML常用表格与标签
前端·html
疯狂的沙粒6 小时前
如何在Vue项目中应用TypeScript?应该注意那些点?
前端·vue.js·typescript
小镇程序员6 小时前
vue2 src_Todolist全局总线事件版本
前端·javascript·vue.js
野槐6 小时前
前端图像处理(一)
前端