vue.js内置组件之keep-alive组件使用


Posted in Javascript onJuly 10, 2018

keep-alive是Vue.js的一个内置组件。<keep-alive> 包裹动态组件时,会缓存不活动的组件实例,而不是销毁它们。它自身不会渲染一个 DOM 元素,也不会出现在父组件链中。 当组件在 <keep-alive> 内被切换,它的 activated 和 deactivated 这两个生命周期钩子函数将会被对应执行。 它提供了include与exclude两个属性,允许组件有条件地进行缓存。

举个栗子

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

vue.js内置组件之keep-alive组件使用

在点击button时候,两个input会发生切换,但是这时候这两个输入框的状态会被缓存起来,input标签中的内容不会因为组件的切换而消失。

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

<keep-alive include="a">
 <component></component>
</keep-alive>

只缓存组件别民name为a的组件

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

除了name为a的组件,其他都缓存下来

生命周期钩子

生命钩子 keep-alive提供了两个生命钩子,分别是activated与deactivated。

因为keep-alive会将组件保存在内存中,并不会销毁以及重新创建,所以不会重新调用组件的created等方法,需要用activated与deactivated这两个生命钩子来得知当前组件是否处于活动状态。

深入keep-alive组件实现

vue.js内置组件之keep-alive组件使用 

查看vue--keep-alive组件源代码可以得到以下信息

created钩子会创建一个cache对象,用来作为缓存容器,保存vnode节点。

props: {
 include: patternTypes,
 exclude: patternTypes,
 max: [String, Number]
},
created () {
 // 创建缓存对象
 this.cache = Object.create(null)
 // 创建一个key别名数组(组件name)
 this.keys = []
},

destroyed钩子则在组件被销毁的时候清除cache缓存中的所有组件实例。

destroyed () {
 /* 遍历销毁所有缓存的组件实例*/
 for (const key in this.cache) {
  pruneCacheEntry(this.cache, key, this.keys)
 }
},

:::demo

render () {
 /* 获取插槽 */
 const slot = this.$slots.default
 /* 根据插槽获取第一个组件组件 */
 const vnode: VNode = getFirstComponentChild(slot)
 const componentOptions: ?VNodeComponentOptions = vnode && vnode.componentOptions
 if (componentOptions) {
 // 获取组件的名称(是否设置了组件名称name,没有则返回组件标签名称)
 const name: ?string = getComponentName(componentOptions)
 // 解构对象赋值常量
 const { include, exclude } = this
 if ( /* name不在inlcude中或者在exlude中则直接返回vnode */
  // not included
  (include && (!name || !matches(include, name))) ||
  // excluded
  (exclude && name && matches(exclude, name))
 ) {
  return vnode
 }
 const { cache, keys } = this
 const key: ?string = vnode.key == null
  // same constructor may get registered as different local components
  // so cid alone is not enough (#3269)
  ? componentOptions.Ctor.cid + (componentOptions.tag ? `::${componentOptions.tag}` : '')
  : vnode.key
 if (cache[key]) { // 判断当前是否有缓存,有则取缓存的实例,无则进行缓存
  vnode.componentInstance = cache[key].componentInstance
  // make current key freshest
  remove(keys, key)
  keys.push(key)
 } else {
  cache[key] = vnode
  keys.push(key)
  // 判断是否设置了最大缓存实例数量,超过则删除最老的数据,
  if (this.max && keys.length > parseInt(this.max)) {
  pruneCacheEntry(cache, keys[0], keys, this._vnode)
  }
 }
 // 给vnode打上缓存标记
 vnode.data.keepAlive = true
 }
 return vnode || (slot && slot[0])
}
// 销毁实例
function pruneCacheEntry (
 cache: VNodeCache,
 key: string,
 keys: Array<string>,
 current?: VNode
) {
 const cached = cache[key]
 if (cached && (!current || cached.tag !== current.tag)) {
 cached.componentInstance.$destroy()
 }
 cache[key] = null
 remove(keys, key)
}
// 缓存
function pruneCache (keepAliveInstance: any, filter: Function) {
 const { cache, keys, _vnode } = keepAliveInstance
 for (const key in cache) {
 const cachedNode: ?VNode = cache[key]
 if (cachedNode) {
  const name: ?string = getComponentName(cachedNode.componentOptions)
  // 组件name 不符合filler条件, 销毁实例,移除cahe
  if (name && !filter(name)) {
  pruneCacheEntry(cache, key, keys, _vnode)
  }
 }
 }
}
// 筛选过滤函数
function matches (pattern: string | RegExp | Array<string>, name: string): boolean {
 if (Array.isArray(pattern)) {
 return pattern.indexOf(name) > -1
 } else if (typeof pattern === 'string') {
 return pattern.split(',').indexOf(name) > -1
 } else if (isRegExp(pattern)) {
 return pattern.test(name)
 }
 /* istanbul ignore next */
 return false
}
// 检测 include 和 exclude 数据的变化,实时写入读取缓存或者删除
mounted () {
 this.$watch('include', val => {
 pruneCache(this, name => matches(val, name))
 })
 this.$watch('exclude', val => {
 pruneCache(this, name => !matches(val, name))
 })
},

:::

通过查看Vue源码可以看出,keep-alive默认传递3个属性,include 、exclude、max, max 最大可缓存的长度

结合源码我们可以实现一个可配置缓存的router-view

<!--exclude - 字符串或正则表达式。任何匹配的组件都不会被缓存。-->
<!--TODO 匹配首先检查组件自身的 name 选项,如果 name 选项不可用,则匹配它的局部注册名称-->
<keep-alive :exclude="keepAliveConf.value">
 <router-view class="child-view" :key="$route.fullPath"></router-view>
</keep-alive>
<!-- 或者 -->
<keep-alive :include="keepAliveConf.value">
 <router-view class="child-view" :key="$route.fullPath"></router-view>
</keep-alive>
<!-- 具体使用 include 还是exclude 根据项目是否需要缓存的页面数量多少来决定-->

创建一个keepAliveConf.js 放置需要匹配的组件名

// 路由组件命名集合
 var arr = ['component1', 'component2'];
 export default {value: routeList.join()};

配置重置缓存的全局方法

import keepAliveConf from 'keepAliveConf.js'
Vue.mixin({
 methods: {
 // 传入需要重置的组件名字
 resetKeepAive(name) {
  const conf = keepAliveConf.value;
  let arr = keepAliveConf.value.split(',');
  if (name && typeof name === 'string') {
   let i = arr.indexOf(name);
   if (i > -1) {
    arr.splice(i, 1);
    keepAliveConf.value = arr.join();
    setTimeout(() => {
     keepAliveConf.value = conf
    }, 500);
   }
  }
 },
 }
})

在合适的时机调用调用this.resetKeepAive(name),触发keep-alive销毁组件实例;

vue.js内置组件之keep-alive组件使用

Vue.js内部将DOM节点抽象成了一个个的VNode节点,keep-alive组件的缓存也是基于VNode节点的而不是直接存储DOM结构。它将满足条件的组件在cache对象中缓存起来,在需要重新渲染的时候再将vnode节点从cache对象中取出并渲染。

总结

以上所述是小编给大家介绍的vue.js内置组件之keep-alive组件使用,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Javascript 相关文章推荐
让getElementsByName适应IE和firefox的方法
Sep 24 Javascript
jQuery的实现原理的模拟代码 -4 重要的扩展函数 extend
Aug 03 Javascript
jquery教程限制文本框只能输入数字和小数点示例分享
Jan 13 Javascript
jquery实现翻动fadeIn显示的方法
Mar 05 Javascript
JavaScript获取IP获取的是IPV6 如何校验
Jun 12 Javascript
浅谈JavaScript中变量和函数声明的提升
Aug 09 Javascript
node.js的事件机制
Feb 08 Javascript
Vue实现购物车功能
Apr 27 Javascript
Bootstrap table学习笔记(2) 前后端分页模糊查询
May 18 Javascript
Vue 源码分析之 Observer实现过程
Mar 29 Javascript
vue路由切换之淡入淡出的简单实现
Oct 31 Javascript
jquery实现进度条状态展示
Mar 26 jQuery
小程序图片剪裁加旋转的示例代码
Jul 10 #Javascript
vue使用中的内存泄漏【推荐】
Jul 10 #Javascript
Vue脚手架的简单使用实例
Jul 10 #Javascript
vue自定义移动端touch事件之点击、滑动、长按事件
Jul 10 #Javascript
微信小程序中换行空格(多个空格)写法详解
Jul 10 #Javascript
在小程序中使用腾讯视频插件播放教程视频的方法
Jul 10 #Javascript
Angular5中提取公共组件之radio list的实例代码
Jul 10 #Javascript
You might like
Amazon Prime Video平台《无限住人 -IMMORTAL-》2020年开始TV放送!
2020/03/06 日漫
第4章 数据处理-php数组的处理-郑阿奇
2011/07/04 PHP
LotusPhp笔记之:基于ObjectUtil组件的使用分析
2013/05/06 PHP
coreseek 搜索英文的问题详解
2013/06/08 PHP
php删除字符串末尾子字符,删除开始字符,删除两端字符(实现代码)
2013/06/27 PHP
php 获取今日、昨日、上周、本月的起始时间戳和结束时间戳的方法
2013/09/28 PHP
记录一次排查PHP脚本执行卡住的问题
2016/12/27 PHP
JavaScript中常见陷阱小结
2010/04/27 Javascript
JS 事件绑定函数代码
2010/04/28 Javascript
JS判断客服QQ号在线还是离线状态的方法
2015/01/13 Javascript
详解JavaScript语言的基本语法要求
2015/11/20 Javascript
canvas 画布在主流浏览器中的尺寸限制详细介绍
2016/12/15 Javascript
jquery 正整数数字校验正则表达式
2017/01/10 Javascript
原生JS+CSS实现炫酷重力模拟弹跳系统的登录页面
2017/11/01 Javascript
禁止弹窗中蒙层底部页面跟随滚动的几种方法
2017/12/07 Javascript
详解vue项目中如何引入全局sass/less变量、function、mixin
2018/06/02 Javascript
js操作table中tr的顺序实现上移下移一行的效果
2018/11/22 Javascript
解决Vue项目打包后打开index.html页面显示空白以及图片路径错误的问题
2019/10/25 Javascript
WebStorm无法正确识别Vue3组合式API的解决方案
2021/02/18 Vue.js
[02:03]风行者至宝清风环佩外观展示
2020/09/05 DOTA
centos系统升级python 2.7.3
2014/07/03 Python
使用Python脚本实现批量网站存活检测遇到问题及解决方法
2016/10/11 Python
简单实现python进度条脚本
2017/12/18 Python
简单的python协同过滤程序实例代码
2018/01/31 Python
详解Python logging调用Logger.info方法的处理过程
2019/02/12 Python
使用Python创建简单的HTTP服务器的方法步骤
2019/04/26 Python
10款最好的Python开发编辑器
2019/07/03 Python
在Python中利用pickle保存变量的实例
2019/12/30 Python
numpy中生成随机数的几种常用函数(小结)
2020/08/18 Python
使用纯HTML5编写一款网页上的时钟的代码分享
2015/11/16 HTML / CSS
CSS3 画基本图形,圆形、椭圆形、三角形等
2016/09/20 HTML / CSS
法国票务网站:Ticketmaster法国
2018/07/09 全球购物
继承时候类的执行顺序问题,一般都是选择题,问你将会打印出什么?
2015/11/18 面试题
离婚协议书怎么写
2014/09/12 职场文书
再见,2019我们不负使命;你好,2020我们砥砺前行
2020/01/03 职场文书
比较几种Redis集群方案
2021/06/21 Redis