vue缓存之keep-alive的理解和应用详解


Posted in Javascript onNovember 02, 2020

官方解释:

<keep-alive> 包裹动态组件时,会缓存不活动的组件实例,而不是销毁它们。和 <transition> 相似,<keep-alive> 是一个抽象组件:它自身不会渲染一个 DOM 元素,也不会出现在组件的父组件链中。

当组件在 <keep-alive> 内被切换,它的 activated 和 deactivated 这两个生命周期钩子函数将会被对应执行。

主要用于保留组件状态或避免重新渲染。

keep-alive 是 Vue 的内置组件,在组件切换过程中将状态保留在内存中,等再次访问的时候,还保持着离开之前的所有状态,而不是重新初始化。也就是所谓的组件缓存。

我们知道,使用路由vue-router切换组件的时候是不保存状态的,它进行router.push()或router.push()或router.replace()的时候,旧组件会被销毁,新组件会被新建,然后走一遍完整的生命周期。所以缓存经常与router-view一起出现:

<keep-alive>
  <router-view /> <!-- 所有路径匹配到的视图组件都会被缓存 -->
</keep-alive>

被包含在 keep-alive 中创建的组件,会多出两个生命周期的钩子: activated 与 deactivated:

1. activated:在 keep-alive 组件激活时调用
2. deactivated:在 keep-alive 组件停用时调用

注意: 只有组件被 keep-alive 包裹时,这两个生命周期函数才会被调用。这两个钩子在服务器端渲染期间不被调用。

应用场景:

官网有一个多标签界面的例子,介绍的还是蛮详细的。

我们在实际开发项目中会有一些需求,比如跳转到详情页面时,需要保持列表页的滚动条的位置,返回的时候依然在这个位置,这样可以提高用户体验,这个时候就可以使用缓存组件 keep-alive 来解决。

设置了 keep-alive 缓存的组件,会多出两个生命周期钩子:

  • 首次进入组件时:beforeRouteEnter > beforeCreate > created > mounted > activated > ... ... > beforeRouteLeave > deactivated
  • 再次进入组件时:beforeRouteEnter > activated > ... ... > beforeRouteLeave > deactivated

可以看到,缓存的组件中 activated 钩子函数每次都会触发,所以可以通过这个钩子判断,当前组件时需要使用缓存的数据还是重新调用接口加载数据。如果未使用keep-alive 组件,则在页面回退时会重新渲染页面,首次进入组件的一系列生命周期也会一一被触发。

离开组件时,使用了 keep-alive 不会调用 beforeDestroy 和 destroyed 钩子,因为组件没被销毁,被缓存起来了。所以 deactivated 这个钩子可以看作是 beforeDestroy 和 destroyed 的代替,缓存组件销毁的时候要做的一些操作可以放在这个里面。

需求案例

最近项目中碰到需要缓存的场景,主要还是列表页到详情页的跳转,但列表页存在多级关系,具体需求如下:

vue缓存之keep-alive的理解和应用详解

初次进入此页面,默认展示左侧的树形结构菜单,点击某一菜单,右侧加载该菜单相应的数据列表,由列表进入详情内页,然后再返回该页面,希望该页面保留了用户之前选择的树形菜单及数据列表。若从其他页面进入此页面,则不需要缓存。

案例实践

思路:结合 router 中设置 meta 信息,缓存列表页。
1. 设置路由的 meta 信息

const List = () => import(/* webpackChunkName: "list" */ '../pages/List.vue')
const Detail = () => import(/* webpackChunkName: "detail" */ '../pages/Detail.vue')
{
  path: 'list',
  name: 'list',
  component: List,
  meta: {
    title: '列表',
    keepAlive: true, //需要缓存
    isKeep: false
  }
},
{
  path: 'dist',
  name: 'detail',
  component: Detail
}

2. 修改渲染匹配视图组件 router-view(一般是 app.vue 文件,根据实际需求会不一样)

<div class="container">
  <keep-alive> 
    <!-- 需要缓存的视图组件 -->
    <router-view v-if="$route.meta.keepAlive"></router-view> 
   </keep-alive>
   <!-- 不需要缓存的视图组件 -->
   <router-view v-if="!$route.meta.keepAlive"></router-view>
</div>

也可以使用 keep-alive 组件的 include/exclude 属性,include 表示要缓存的组件名(定义时的 name 属性),而 exclude 相反,匹配到的组件不会被缓存。

<div class="container">
  <keep-alive include="list">
    <router-view></router-view> 
   </keep-alive>
</div>

3. 在需要缓存的页面中,通过导航守卫 beforeRouteEnter 和 activated 钩子判断使用缓存还是重新渲染

beforeRouteEnter (to, from, next) {
  // 只在详情返回时做缓存
  if (from.name === 'detail') {
    to.meta.isKeep = true
  } else {
    to.meta.isKeep = false
  }
  next()
},
activated () {
  if(this.$route.meta.isKeep) {
    // 详情返回,取缓存数据
  } else {
    // 重新渲染,在这里调用加载请求
  }
}

此处 beforeRouteEnter 钩子也可以使用 watch 属性监听路由的变化:

watch: {
  $route(to, from) {
    //通过to/from.path判断是否是需要缓存的路径然后添加逻辑
  }
}

问题:

从详情返回列表时正常,但当用户在详情页按 F5 刷新之后,再返回列表就不能保留离开之前的状态了,因为这时页面重载了。

解决办法:

在离开当前之前,将信息储存在 localStorage 中,当详情数据刷新后,手动触发加载请求。

到此这篇关于vue缓存之keep-alive的理解和应用详解的文章就介绍到这了,更多相关vue keep-alive内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Javascript 相关文章推荐
28个JS验证函数收集
Mar 02 Javascript
jquery getScript动态加载JS方法改进详解
Nov 15 Javascript
文本框只能选择数据到文本框禁止手动输入
Nov 22 Javascript
JavaScript异步回调的Promise模式封装实例
Jun 07 Javascript
JavaScript控制浏览器全屏及各种浏览器全屏模式的方法、属性和事件
Dec 20 Javascript
javascript 继承学习心得总结
Mar 17 Javascript
BootStrap的alert提示框的关闭后再显示怎么解决
May 17 Javascript
使用Bootstrap框架制作查询页面的界面实例代码
May 27 Javascript
AngularJS中directive指令使用之事件绑定与指令交互用法示例
Nov 22 Javascript
纯JS实现图片验证码功能并兼容IE6-8(推荐)
Apr 19 Javascript
JavaScript之underscore_动力节点Java学院整理
Jul 03 Javascript
微信小程序-API接口安全详解
Jul 16 Javascript
详解vue-router的导航钩子(导航守卫)
Nov 02 #Javascript
vue+elementUI中表格高亮或字体颜色改变操作
Nov 02 #Javascript
vue element-ui中table合计指定列求和实例
Nov 02 #Javascript
vue 动态添加class,三个以上的条件做判断方式
Nov 02 #Javascript
vue 公共列表选择组件,引用Vant-UI的样式方式
Nov 02 #Javascript
在vant 中使用cell组件 定义图标该图片和位置操作
Nov 02 #Javascript
Vant picker 多级联动操作
Nov 02 #Javascript
You might like
PHP怎样调用MSSQL的存储过程
2006/10/09 PHP
随时给自己贴的图片加文字的php水印
2007/03/16 PHP
用PHP即时捕捉PHP中的错误并发送email通知的实现代码
2013/01/19 PHP
php实现字符串首字母大写和单词首字母大写的方法
2015/03/14 PHP
利用phpexcel对数据库数据的导入excel(excel筛选)、导出excel
2017/04/27 PHP
用Javscript实现表单复选框的全选功能
2007/05/25 Javascript
jQuery 常见学习网站与参考书
2009/11/09 Javascript
asp.net网站开发中用jquery实现滚动浏览器滚动条加载数据(类似于腾讯微博)
2012/03/14 Javascript
js实现简单鼠标跟随效果的方法
2015/04/10 Javascript
JavaScript获取表格(table)当前行的值、删除行、增加行
2015/07/03 Javascript
使用js复制链接中的部分文字的方法
2015/07/30 Javascript
JS实现很实用的对联广告代码(可自适应高度)
2015/09/18 Javascript
jQuery实现的分子运动小球碰撞效果
2016/01/27 Javascript
js实现精确到毫秒的倒计时效果
2016/08/05 Javascript
js 调用百度分享功能
2017/02/27 Javascript
微信小程序导航栏滑动定位功能示例(实现CSS3的positionsticky效果)
2019/01/24 Javascript
JS div匀速移动动画与变速移动动画代码实例
2019/03/26 Javascript
jquery树形插件zTree高级使用详解
2019/08/16 jQuery
Vue.js暴露方法给WebView的使用操作
2020/09/07 Javascript
微信小程序实现自定义动画弹框/提示框的方法实例
2020/11/06 Javascript
Python使用xlrd模块操作Excel数据导入的方法
2015/05/26 Python
详解使用python crontab设置linux定时任务
2016/12/08 Python
利用Celery实现Django博客PV统计功能详解
2017/05/08 Python
详解Python循环作用域与闭包
2019/03/21 Python
Python编程学习之如何判断3个数的大小
2019/08/07 Python
德国高性价比网上药店:medpex
2017/07/09 全球购物
日本小田急百货官网:Odakyu
2018/07/19 全球购物
DBA数据库管理员JAVA程序员架构师必看
2016/02/07 面试题
单位办理社保介绍信
2014/01/10 职场文书
企业法人授权委托书
2014/04/03 职场文书
大学生安全责任书
2014/07/25 职场文书
党支部三会一课计划
2014/09/24 职场文书
解决thinkphp6(tp6)在状态码500下不报错,或者显示错误“Malformed UTF-8 characters”的问题
2021/04/01 PHP
python关于集合的知识案例详解
2021/05/30 Python
Python基础教程,Python入门教程(超详细)
2021/06/24 Python
Redis 报错 error:NOAUTH Authentication required
2022/05/15 Redis