深入理解Vue keep-alive及实践总结


Posted in Javascript onAugust 21, 2019

什么是 keep-alive

在平常开发中,有部分组件没有必要多次初始化,这时,我们需要将组件进行持久化,使组件的状态维持不变,在下一次展示时,也不会进行重新初始化组件。

也就是说,keepalive 是 Vue 内置的一个组件,可以使被包含的组件保留状态,或避免重新渲染 。也就是所谓的组件缓存
<keep-alive>是Vue的内置组件,能在组件切换过程中将状态保留在内存中,防止重复渲染DOM。

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

prop:

  • include: 字符串或正则表达式。只有匹配的组件会被缓存。
  • exclude: 字符串或正则表达式。任何匹配的组件都不会被缓存。

keep-alive的声明周期执行

页面第一次进入,钩子的触发顺序

created-> mounted-> activated,退出时触发 deactivated

当再次进入(前进或者后退)时,只触发 activated

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

基本用法

<!--被keepalive包含的组件会被缓存-->
<keep-alive>
  <component><component />
</keep-alive>

被keepalive包含的组件不会被再次初始化,也就意味着不会重走生命周期函数
但是有时候是希望我们缓存的组件可以能够再次进行渲染,这时 Vue 为我们解决了这个问题
被包含在 keep-alive 中创建的组件,会多出两个生命周期的钩子: activated 与 deactivated:

  • activated 当 keepalive 包含的组件再次渲染的时候触发
  • deactivated 当 keepalive 包含的组件销毁的时候触发

keepalive是一个抽象的组件,缓存的组件不会被 mounted,为此提供activated和deactivated钩子函数

参数理解

keepalive 可以接收3个属性做为参数进行匹配对应的组件进行缓存:

  • include 包含的组件(可以为字符串,数组,以及正则表达式,只有匹配的组件会被缓存)
  • exclude 排除的组件(以为字符串,数组,以及正则表达式,任何匹配的组件都不会被缓存)
  • max 缓存组件的最大值(类型为字符或者数字,可以控制缓存组件的个数)

注:当使用正则表达式或者数组时,一定要使用 v-bind

<!-- 将(只)缓存组件name为a或者b的组件, 结合动态组件使用 -->
<keep-alive include="a,b">
 <component></component>
</keep-alive>

<!-- 组件name为c的组件不缓存(可以保留它的状态或避免重新渲染) -->
<keep-alive exclude="c"> 
 <component></component>
</keep-alive>

<!-- 使用正则表达式,需使用v-bind -->
<keep-alive :include="/a|b/">
 <component :is="view"></component>
</keep-alive>

<!-- 动态判断 -->
<keep-alive :include="includedComponents">
 <router-view></router-view>
</keep-alive>

<!-- 如果同时使用include,exclude,那么exclude优先于include, 下面的例子只缓存a组件 -->
<keep-alive include="a,b" exclude="b"> 
 <component></component>
</keep-alive>

<!-- 如果缓存的组件超过了max设定的值5,那么将删除第一个缓存的组件 -->
<keep-alive exclude="c" max="5"> 
 <component></component>
</keep-alive>

遇见 vue-router 结合router使用,缓存部分页面

所有路径下的视图组件都会被缓存

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

如果只想要router-view里面的某个组件被缓存,怎么办?

  • 使用 include/exclude
  • 使用 meta 属性

1、用 include (exclude例子类似)

缺点:需要知道组件的 name,项目复杂的时候不是很好的选择

<keep-alive include="a">
  <router-view>
    <!-- 只有路径匹配到的 include 为 a 组件会被缓存 -->
  </router-view>
</keep-alive>

2、使用 meta 属性

优点:不需要例举出需要被缓存组件名称

使用$route.meta的keepAlive属性:

<keep-alive>
  <router-view v-if="$route.meta.keepAlive"></router-view>
</keep-alive>
<router-view v-if="!$route.meta.keepAlive"></router-view>

需要在router中设置router的元信息meta:

//...router.js
export default new Router({
 routes: [
  {
   path: '/',
   name: 'Hello',
   component: Hello,
   meta: {
    keepAlive: false // 不需要缓存
   }
  },
  {
   path: '/page1',
   name: 'Page1',
   component: Page1,
   meta: {
    keepAlive: true // 需要被缓存
   }
  }
 ]
})

【加盐】使用 router.meta 拓展

假设这里有 3 个路由: A、B、C。

需求:

  • 默认显示 A
  • B 跳到 A,A 不刷新
  • C 跳到 A,A 刷新

实现方式

在 A 路由里面设置 meta 属性:

{
    path: '/',
    name: 'A',
    component: A,
    meta: {
      keepAlive: true // 需要被缓存
    }
}

在 B 组件里面设置 beforeRouteLeave:

export default {
    data() {
      return {};
    },
    methods: {},
    beforeRouteLeave(to, from, next) {
       // 设置下一个路由的 meta
      to.meta.keepAlive = true; // 让 A 缓存,即不刷新
      next();
    }
};

在 C 组件里面设置 beforeRouteLeave:

export default {
    data() {
      return {};
    },
    methods: {},
    beforeRouteLeave(to, from, next) {
      // 设置下一个路由的 meta
      to.meta.keepAlive = false; // 让 A 不缓存,即刷新
      next();
    }
};

这样便能实现 B 回到 A,A 不刷新;而 C 回到 A 则刷新。

防坑指南

1.keep-alive 先匹配被包含组件的 name 字段,如果 name 不可用,则匹配当前组件 components 配置中的注册名称。
2.keep-alive 不会在函数式组件中正常工作,因为它们没有缓存实例。
3.当匹配条件同时在 include 与 exclude 存在时,以 exclude 优先级最高(当前vue 2.4.2 version)。比如:包含于排除同时匹配到了组件A,那组件A不会被缓存。
4.包含在 keep-alive 中,但符合 exclude ,不会调用 activated 和 deactivated。

实现前进刷新,后退不刷新

感谢 iceuncle 分享的 《vue实现前进刷新,后退不刷新》。

总结

路由大法不错,不需要关心哪个页面跳转过来的,只要 router.go(-1) 就能回去,不需要额外参数。

在非单页应用的时候,keep-alive 并不能有效的缓存了= =

keep-alive生命周期钩子函数:activated、deactivated

使用<keep-alive>会将数据保留在内存中,如果要在每次进入页面的时候获取最新的数据,需要在activated阶段获取数据,承担原来created钩子中获取数据的任务。

附录

生命周期函数:就是vue在某个时间段会自动执行的函数

  • beforeCreate(){}在执行的时候,data还有methods都没有被初始化
  • created(){} data还有methods都被初始化好了,如果要调用 methods 方法或者操作 data 里面的数据,最早只能在 created 里面进行操作。
  • beforeMount(){} 表示模板已经在内存中编辑完成了,但是尚未渲染到模板页面中。即页面中的元素,没有被真正的替换过来,只是之前写的一些模板字符串。
  • mounted(){} 表示内存中模板已经真实的挂载到页面中去了,用户可以看到渲染好的界面了

注意这是一个生命周期函数的最后一个函数了,执行完这个函数表示 整个vue实例已经初始化完成了,组件脱离了创建阶段,进入运行阶段。

下面是运行期间的两个生命周期函数的钩子:

beforeUpdate(){} 表示我们的界面还没更新 但是data里面的数据是最新的。即页面尚未和最新的data里面的数据保持同步。

update(){} 表示页面和data里面的数据已经包吃同步了 都是最新的。

beforeDestory(){} 当执行这个生命周期钩子的时候 vue的实例从运行阶段进入销毁阶段 此时实例身上的data 还有 methods处于可用的状态。

Destoryed(){} 表示组件已经完全被销毁了 组件中所有的实例方法都是不能用了

参考:

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
javascript showModalDialog 内跳转页面的问题
Nov 25 Javascript
JQuery循环滚动图片代码
Dec 08 Javascript
jquery获取元素值的方法(常见的表单元素)
Nov 15 Javascript
jquery无刷新验证邮箱地址实现实例
Feb 19 Javascript
浅谈JavaScript Array对象
Dec 29 Javascript
jquery右下角自动弹出可关闭的广告层
May 08 Javascript
jquery地址栏链接与a标签链接匹配之特效代码总结
Aug 24 Javascript
JS使用eval解析JSON的注意事项分析
Nov 14 Javascript
微信小程序手势操作之单触摸点与多触摸点
Mar 10 Javascript
angularjs实现过滤并替换关键字小功能
Sep 19 Javascript
在vscode里使用.vue代码模板的方法
Apr 28 Javascript
js实现3D照片墙效果
Oct 28 Javascript
vue element 生成无线级左侧菜单的实现代码
Aug 21 #Javascript
微信小程序仿今日头条导航栏滚动解析
Aug 20 #Javascript
Vue中axios的封装(报错、鉴权、跳转、拦截、提示)
Aug 20 #Javascript
Vue formData实现图片上传
Aug 20 #Javascript
Angular8 Http拦截器简单使用教程
Aug 20 #Javascript
vue实现axios图片上传功能
Aug 20 #Javascript
扫微信小程序码实现网站登陆实现解析
Aug 20 #Javascript
You might like
PHP封装curl的调用接口及常用函数详解
2018/05/31 PHP
php ZipArchive实现多文件打包下载实例
2019/10/31 PHP
Jquery对select的增、删、改、查操作
2015/02/06 Javascript
Bootstrap模仿起筷首页效果
2016/05/09 Javascript
手机浏览器 后退按钮强制刷新页面方法总结
2016/10/09 Javascript
javascript 注释代码的几种方法总结
2017/01/04 Javascript
tablesorter.js表格排序使用方法(支持中文排序)
2017/02/10 Javascript
javascript实现动态显示颜色块的报表效果
2017/04/10 Javascript
ES6教程之for循环和Map,Set用法分析
2017/04/10 Javascript
Vue精简版风格指南(推荐)
2018/01/30 Javascript
vue项目实战总结篇
2018/02/11 Javascript
详解Vue组件之间通信的七种方式
2019/04/14 Javascript
SpringBoot+Vue开发之Login校验规则、实现登录和重置事件
2020/10/19 Javascript
[06:49]2018DOTA2国际邀请赛寻真——VirtusPro傲视群雄
2018/08/12 DOTA
[00:56]PWL开团时刻DAY8——追追追追追!
2020/11/09 DOTA
动态规划之矩阵连乘问题Python实现方法
2017/11/27 Python
使用python判断jpeg图片的完整性实例
2019/06/10 Python
Python 获取windows桌面路径的5种方法小结
2019/07/15 Python
Django密码系统实现过程详解
2019/07/19 Python
Pytorch Tensor的统计属性实例讲解
2019/12/30 Python
python查看矩阵的行列号以及维数方式
2020/05/22 Python
CSS3 box-sizing属性
2009/04/17 HTML / CSS
纯CSS3实现8组超炫酷鼠标滑过图片动画
2016/03/16 HTML / CSS
html5声频audio和视频video等新特性详细说明
2012/12/26 HTML / CSS
Linden Leaves官网:新西兰纯净护肤品
2020/12/20 全球购物
幼师自我鉴定
2014/02/01 职场文书
构建高效课堂实施方案
2014/03/13 职场文书
大学奖学金获奖感言
2014/08/15 职场文书
人事行政主管岗位职责
2015/04/09 职场文书
民间借贷纠纷案件代理词
2015/05/26 职场文书
中国文明网2015年“向国旗敬礼”活动网上签名寄语
2015/09/24 职场文书
如何用JS实现简单的数据监听
2021/05/06 Javascript
Flask搭建一个API服务器的步骤
2021/05/28 Python
分位数回归模型quantile regeression应用详解及示例教程
2021/11/02 Python
Python+Selenium实现读取网易邮箱验证码
2022/03/13 Python
win11如何查看端口是否被占用? Win11查看端口是否占用的技巧
2022/04/05 数码科技