keep-alive详解
- 1、简介
- 2、keep-alive的使用效果
- 未使用keep-alive的效果图
- 使用keep-alive的效果图
- include和exclude指定是否缓存某些组件
- 使用keep-alive的钩子函数执行顺序问题
- 3、keep-alive的应用场景举例
- 4、总结
1、简介
- keep-alive 是 Vue 的内置组件,当它包裹动态组件时,会缓存不活动的组件实例,而不是销毁它们。
- 原理: 在 created 函数调用时将需要缓存的 VNode 节点保存在 this.cache 中,在 render(页面渲染) 时,如果 VNode 的 name 符合缓存条件(可以用 include 以及 exclude 控制),则会从 this.cache 中取出之前缓存的 VNode 实例进行渲染。
2、keep-alive的使用效果
demo分为上面的路由导航部分,下面的内容区部分。点击上面的路由导航,路由视图渲染对应的路由组件。效果图如下:
未使用keep-alive的效果图
对应代码
// #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的效果图
对应代码
<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 命名
// 指定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组件,我们先看一下代码,再在钩子中打印出对应的顺序。就知道钩子执行的顺序了:
<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、总结
- 用于保留组件状态或避免重新渲染,包裹动态组件时,会缓存不活动的组件实例,而不是销毁它们。
- 当组件在 keep-alive内被切换,它的 activated 和 deactivated 这两个生命周期钩子函数将会被对应执行。
- 页面第一次进入时,生命周期触发:created-mounted-activated,后续进入和离开 activated --> deactivated。
- <keep-alive includ=“xxx”> <router-view /> </keep-alive> 指定部分 name 为 xxx 的组件会被缓存。