什么是keepalive?

在平常开发中,有部分组件没有必要多次初始化,这时,我们需要将组件进行持久化,使组件的状态维持不变,在下一次展示时,也不会进行重新初始化组件。
也就是说,keepalive 是 Vue 内置的一个组件,可以使被包含的组件保留状态,或避免重新渲染 。也就是所谓的组件缓存

基本用法

<keep-alive><component />  //你的组件
</keep-alive>

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

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

keepalive是一个抽象的组件,缓存的组件不会被mounted,为此提供activated和deactivated钩子函数
在2.1.0 版本后keep-alive新加入了两个属性: include(包含的组件缓存生效) 与 exclude(排除的组件不缓存,优先级大于include) 。

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

  • include包含的组件(可以为字符串,数组,以及正则表达式,只有匹配的组件会被缓存)

  • exclude排除的组件(以为字符串,数组,以及正则表达式,任何匹配的组件都不会被缓存)

  • max缓存组件的最大值(类型为字符或者数字,可以控制缓存组件的个数)

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

<!-- 逗号分隔字符串 -->
<keep-alive include="a,b"><component :is="view"></component>
</keep-alive><!-- 正则表达式 (使用 `v-bind`) -->
<keep-alive :include="/a|b/"><component :is="view"></component>
</keep-alive><!-- 数组 (使用 `v-bind`) -->
<keep-alive :include="['a', 'b']"><component :is="view"></component>
</keep-alive>
// 只缓存组件name为a或者b的组件
<keep-alive include="a,b"> <component />
</keep-alive>

// 组件name为c的组件不缓存(可以保留它的状态或避免重新渲染)

<keep-alive exclude="c"> <component />
</keep-alive>

// 如果同时使用include,exclude,那么exclude优先于include, 下面的例子只缓存a组件

<keep-alive include="a,b" exclude="b"> <component />
</keep-alive>
// 如果缓存的组件超过了max设定的值5,那么将删除第一个缓存的组件
<keep-alive exclude="c" max="5"> <component />
</keep-alive>!!<keep-alive> 不会在函数式组件中正常工作,因为它们没有缓存实例。

配合router使用

router-view也是一个组件,如果直接被包在keepalive里面,那么所有路径匹配到的视图组件都会被缓存,如下:

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

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

  • 使用 include/exclude
  • 使用 meta 属性
    1.使用 include (exclude例子类似)
//只有路径匹配到的 name 为 a 组件会被缓存
<keep-alive include="a"><router-view></router-view>
</keep-alive>

2.使用 meta 属性

// routes 配置
export default [{path: '/',name: 'home',component: Home,meta: {keepAlive: true // 需要被缓存}}, {path: '/profile',name: 'profile',component: Profile,meta: {keepAlive: false // 不需要被缓存}}
]
<keep-alive><router-view v-if="$route.meta.keepAlive"><!-- 这里是会被缓存的视图组件,比如 Home! --></router-view>
</keep-alive><router-view v-if="!$route.meta.keepAlive"><!-- 这里是不会被缓存的视图组件,比如 Profile! -->
</router-view>

!!这里需要注意的是,如果你是通过这种设置meta的方式创建keepAlive的话,keepAlive组件一旦被创建,就不会被销毁了,如果你想通过改变meta的方式销毁keepAlive,这样做是不可行的!!!网上很多教程叫你把meta的keepAlive设置为false,他们到底有没有实验过啊,真坑!那么如果你设置了keepAlive之后,又有某种特殊情况想销毁的话,那要怎么做呢?这里建议通过vuex配合设置include来决定页面是否需要keepAlive,下面是具体实现例子。

比如,你有这个需求:
首页是A页面
B页面跳转到A,A页面需要缓存
C页面跳转到A,A页面不需要被缓存

在你需要的设置缓存的页面:

  <keep-alive :include="keepAlivePage"><router-view></router-view></keep-alive><script>computed: {...mapGetters(['keepAlivePage'])}
</script>

在vuex中(我这里把vuex按照模块划分了,如果不是用Moudules这种的话自行转义哈)

getters中

const getters = {keepAlivePage: state => state.settings.keepAlivePage // 获取需要缓存的页面
}
export default getters

state中

const state = {keepAlivePage: [] // 需要缓存的页面,如果说你一开始就要缓存,那么你可以在这里设置初始值,如果你不需一开始就设置缓存,那么设置为空,再通过某种条件通过mutations或者actions改变keepAlivePage
}

如果说我要增加一个页面缓存,那么我在我需要增加的代码逻辑上增加下面一行代码

doSomeThing() {doSomeThing(1001).then(res => {if (res.code === 200 && res.data.length) {doSomeThing....// 把页面keepAlive缓存this.$store.dispatch('settings/addKeepAlivePage', 'Home') //'Home'就是你要增加页面缓存的名称。}})

然后再vuex的actions中

const actions = {addKeepAlivePage ({ commit }, name) {commit('ADD_KEEP_ALVE', name)}
}

vuex的mutations中

const mutations = {ADD_KEEP_ALVE: (state, name) => {state.keepAlivePage = state.keepAlivePage.concat(name)}
}

这样子‘Home’组件就会被添加到缓存之中

注意!!这里要特别注意页面组价的名字要和router设置页面的名字要一一对应,不然的话接下来的需求就会实现不了!!


接下来回到刚刚那个需求,
B页面跳转到A,A页面需要缓存
C页面跳转到A,A页面不需要被缓存

思路是在每个路由的beforeRouteLeave(to, from, next)钩子中设置修改vuex中的keepAlivePage数组,把router的Name名字和keepAlivePage数组对比,如果你要缓存直接添加上就好了,如果不需要就对比里面是否有这个Name,有的话就删除就好了

例如:我在404页面跳转到home界面的话需要清除keepAlive,那么我就可以在beforeRouteLeave这样设置

 methods: {goTo () {this.$router.go(-1)}},beforeRouteLeave (to, from, next) {console.log(to)this.$store.dispatch('settings/changeKeepAlive', to.name)next()}
}

vuex的actions中

 changeKeepAlive ({ commit }, name) {commit('CHANGE_KEEP_ALIVE', name)},

vuex的mutations中

  CHANGE_KEEP_ALIVE: (state, name) => {const keepAlivePage = state.keepAlivePageconst index = keepAlivePage.indexOf(name)if (index > -1) {keepAlivePage.splice(index, 1)}}

这样子我就把keepAlivePage数组中的‘Home’删掉了,如果你要新增keepAlie页面的话,就用刚刚这个方法就好了

 this.$store.dispatch('settings/addKeepAlivePage', 'Home')

OK,现在需求完美解决,有问题可以留言提问

防坑指南
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。

如何在vue中使用keepalive,以及如何移除keepalive相关推荐

  1. vue 递归创建菜单_如何在Vue中创建类似中等的突出显示菜单

    vue 递归创建菜单 by Taha Shashtari 由Taha Shashtari 如何在Vue中创建类似中等的突出显示菜单 (How to Create a Medium-Like Highl ...

  2. 如何在 Vue 中使用 Chart.js - 手把手教你搭可视化数据图表

    本文首发:<如何在 Vue 中使用 Chart.js - 手把手教你搭可视化数据图表> 使用 Chart.js 在 Vue 搭建的后台管理工具里添加炫酷的图表,是所有数据展示类后台必备的功 ...

  3. 如何在 Vue 中导出数据至 Excel 表格 - 卡拉云

    本文首发:<如何在 Vue 中导出数据至 Excel 表格 - 卡拉云> 我们经常需要在 Vue 搭建的后台管理系统里导出数据到 Excel / CSV ,方便我们将数据共享给其他同学或在 ...

  4. 骨架屏技术讲解以及如何在Vue中实现骨架屏

    骨架屏技术讲解以及如何在Vue中实现骨架屏 写在前面 骨架屏是什么 如何实现(原理分析) 一个生动的例子 实现方式(具体实现) 方案一.在模版中来实现骨架屏 方案二.使用一个Base64的图片来作为骨 ...

  5. 如何在Vue 中管理 Mixins(搞懂这两点就足够了)

    转载地址:https://segmentfault.com/a/1190000021772893 当我们的Vue项目功能越来越多时,如果有类似的组件,可能会发现自己一次又一次地复制和粘贴相同的数据.方 ...

  6. vue 数组转集合_思想实验:如何在Vue中使localStorage具有响应式?

    响应式是Vue的最大特色之一.如果你不知道幕后情况,它也是最神秘的地方之一.例如,为什么它不能用于对象和数组,而不能用于诸如 localStorage 之类的其他东西? 让我们回答这个问题,在解决这个 ...

  7. 如何在Vue中使用websocket?

    什么是WebSocket : WebSocket是一种在单个TCP连接上进行全双工通信的协议.WebSocket通信协议于2011年被IETF定为标准RFC 6455,并由RFC7936补充规范. W ...

  8. 如何在vue中优雅的使用ocx控件:控件引用

    最近刚好在做一个自助机项目,限于个人技术栈,也是为了后期更新维护方便,采用了BS的形式来开发. 自助机需要控制摄像头.身份证读卡器.扫描仪.手写签名等硬件,目前只有IE的ocx控件可以提供比较好的支持 ...

  9. 如何在vue中优雅的使用ocx控件:结合iframe

    如果感觉ocx控件会破坏vue代码结构,写起来很别扭,我们可以使用iframe来封装ocx控件. 以串口控件为例,文件包括:serial.html和serial.vue <!DOCTYPE ht ...

最新文章

  1. 我的世界服务器无限小号,我的世界惊现全新无限刷物品bug 服主大大都要注意了...
  2. 用python实现基本A*算法
  3. ITK:在图像中查找连接的组件
  4. ITK:演示所有运算符
  5. html5新增的js api,对HTML5新增JS Api的思考
  6. 进程间通信(IPC)+进程加锁解锁
  7. zen-coding for notepad++,前端最佳手写代码编辑器
  8. hht时频谱 matlab 乱序_MATLAB信号频谱分析FFT详解
  9. unicode编码表_关于编码
  10. 创建maven的web项目,并用jetty调试
  11. 基于http live streaming, 使用vlc + mediastreamsegmenter + apache 实现iOS视频直播
  12. 个人财务管理系统mysql_个人财务管理系统功能模块设计
  13. 最新 Axure 激活码
  14. ECharts地图省市县在对应地图的中心位置
  15. java获取时分秒毫秒_JAVA中如何获取毫秒和微秒数
  16. JSP九大内置对象及其使用教程
  17. 『2021最新~解决』The push refers to a repository [docker.io/
  18. Roman to Integer:转换罗马数字到阿拉伯数字
  19. docker搭建searx_Searx – 尊重隐私的开源搜索引擎
  20. 到底要怎么做,才能不堵车?

热门文章

  1. 【夏季暴强减肥食谱】
  2. SQL之exists、not exists
  3. 研究生复试------3.找圆心
  4. JavaSE面向对象:继承、多态、Super、Object类、重写、static、final、静态成员、懒汉式、饿汉式、单例设计模式、初始化块、抽象类、抽象方法、接口
  5. unity应用实例——从头撸一个全新的FPS游戏(4)
  6. 2006德国世界杯32强口号-励志篇
  7. 3DMAX小白怎么上手?快速讲解3DMAX基本操作心得
  8. 虚拟机免密登录 (SSH 无密登录配置)
  9. Vue.js阿拉伯数字转化成人民币的中文
  10. Severus Snape