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 相关文章推荐
javascript面向对象的方式实现的弹出层效果代码
Jan 28 Javascript
jqeury eval将字符串转换json的方法
Jan 20 Javascript
jQuery表格插件datatables用法总结
Sep 05 Javascript
node.js中的dns.getServers方法使用说明
Dec 08 Javascript
html5+CSS 实现禁止IOS长按复制粘贴功能
Dec 28 Javascript
Vue自定义过滤器格式化数字三位加一逗号实现代码
Mar 23 Javascript
vue添加class样式实例讲解
Feb 12 Javascript
jQuery操作attr、prop、val()/text()/html()、class属性
May 23 jQuery
js实现轮播图效果 z-index实现轮播图
Jan 17 Javascript
js将URL网址转为16进制加密与解密函数
Mar 04 Javascript
vue中的使用token的方法示例
Mar 10 Javascript
关于better-scroll插件的无法滑动bug(2021通过插件解决)
Mar 01 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
玩转图像函数库―常见图形操作
2006/09/03 PHP
PHP程序员最常犯的11个MySQL错误小结
2010/11/20 PHP
yii框架源码分析之创建controller代码
2011/06/28 PHP
php定义一个参数带有默认值的函数实例分析
2015/03/16 PHP
php生成年月日下载列表的方法
2015/04/24 PHP
thinkPHP5.0框架独立配置与动态配置方法
2017/03/17 PHP
php+resumablejs实现的分块上传 断点续传功能示例
2017/04/18 PHP
解决Laravel 使用insert插入数据,字段created_at为0000的问题
2019/10/11 PHP
IE iframe的onload方法分析小结
2010/01/07 Javascript
Jquery颜色选择器ColorPicker实现代码
2012/11/14 Javascript
打印json对象的内容及JSON.stringify函数应用
2013/03/29 Javascript
HTML5之lang属性与dir属性的详解
2013/06/19 Javascript
解析javascript 数组以及json元素的添加删除
2013/06/26 Javascript
js取消单选按钮选中并判断对象是否为空
2013/11/14 Javascript
利用js动态添加删除table行的示例代码
2013/12/16 Javascript
js之ActiveX控件使用说明 new ActiveXObject()
2014/03/03 Javascript
jquery实现点击页面计算点击次数
2015/01/23 Javascript
探讨JavaScript中的Rest参数和参数默认值
2015/07/29 Javascript
javascript类型系统 Array对象学习笔记
2016/01/09 Javascript
javascript解决小数的加减乘除精度丢失的方案
2016/05/31 Javascript
JS失效 提示HTML1114: (UNICODE 字节顺序标记)的代码页 utf-8 覆盖(META 标记)的冲突的代码页 utf-8
2017/06/23 Javascript
浅析为什么a=&quot;abc&quot; 不等于 a=new String(&quot;abc&quot;)
2017/10/25 Javascript
JavaScript设计模式之职责链模式应用示例
2018/08/07 Javascript
微信小程序之判断页面滚动方向的示例代码
2018/08/30 Javascript
详解微信小程序中var、let、const用法与区别
2020/01/11 Javascript
封装一下vue中的axios示例代码详解
2020/02/16 Javascript
Vue-cli3多页面配置详解
2020/03/22 Javascript
python使用rsa加密算法模块模拟新浪微博登录
2014/01/22 Python
Python中super()函数简介及用法分享
2016/07/11 Python
Python数据结构之图的应用示例
2018/05/11 Python
python如何将多个PDF进行合并
2019/08/13 Python
JBL澳大利亚官方商店:扬声器、耳机和音响系统
2018/05/24 全球购物
SQL Server面试题
2013/04/04 面试题
销售人员中英文自荐信
2013/09/22 职场文书
幼儿园运动会加油词
2014/02/14 职场文书
教你怎么用Python生成九宫格照片
2021/05/20 Python