当前位置: 首页 > Web前端 > vue.js

keep-alive实现原理

时间:2023-03-31 20:24:34 vue.js

使用说明keep-alive组件接受三个属性参数:include、exclude、maxinclude来指定需要缓存的组件名称集合。参数格式支持String、RegExp、Array。为字符串时,多个组件名称用逗号分隔。exclude指定不需要缓存的组件名称集合,参数格式与include相同。max指定可以缓存的最大组件数,超过则删除第一个。参数格式支持String和Number。源码分析保活实例会缓存对应组件的VNode。如果缓存命中,则直接从缓存对象中返回对应的VNode。import{isRegExp,remove}from'shared/util'import{getFirstComponentChild}from'core/vdom/helpers/index'typeVNodeCache={[key:string]:?VNode};functiongetComponentName(opts:?VNodeComponentOptions):?string{returnopts&&(opts.Ctor.options.name||opts.tag)}//@doc函数匹配(pattern:string|RegExp|Array,name:string):boolean{if(Array.isArray(pattern)){returnpattern.indexOf(name)>-1}elseif(typeofpattern==='string'){returnpattern.split(',').indexOf(name)>-1}elseif(isRegExp(pattern)){returnpattern.test(name)}/*istanbul忽略下一个*/returnfalse}functionpruneCache(keepAliveInstance:any,filter:Function){const{cache,keys,_vnode}=keepAliveInstancefor(constkey在缓存中){constcachedNode:?VNode=cache[key]if(cachedNode){constname:?string=getComponentName(cachedNode.componentOptions)if(name&&!filter(name)){pruneCacheEntry(cache,key,keys,_vnode)}}}functionpruneCacheEntry(cache:VNodeCache,key:string,keys:Array,current?:VNode){constcached=cache[key复制代码]if(cached&&(!current||cached.tag!==current.tag)){//@doc营销包保存在里面的组件cached.componentInstance.$destroy()}cache[key]=nullremove(keys,key)}constpatternTypes:Array=[String,RegExp,Array]//@doc支持字符串、规则、数组格式exportdefault{name:'keep-alive',abstract:true,props:{include:patternTypes,exclude:patternTypes,max:[String,Number]},created(){this.cache=Object.create(null)this.keys=[]},destroyed(){for(constkeyinthis.cache)复制代码{pruneCacheEntry(this.cache,key,this.keys)}},mounted(){this.$watch('include',val=>{pruneCache(this,name=>matches(val,name))})这个.$watch('排除',val=>{pruneCache(this,name=>!matches(val,name))})},render(){constslot=this.$slots.default//@doc获取keep-alive中的内容constvnode:VNode=getFirstComponentChild(slot)//@doc获取第一个组件constcomponentOptions:?VNodeComponentOptions=vnode&&vnode.componentOptionsif(componentOptions){//检查模式constname:?string=getComponentName(componentOptions)const{include,exclude}=this//@doc从匹配规则可以看出exclude比include优先级高(exclude,name))){//@doc如果没有设置缓存,直接返回vnodereturnvnode}const{cache,keys}=thisconstkey:?string=vnode.key==null//同一个构造函数可能会得到注册为不同的本地组件//所以仅cid是不够的(#3269)?componentOptions.Ctor.cid+(componentOptions.tag?`::${componentOptions.tag}`:''):vnode.keyif(cache[key]){vnode.componentInstance=cache[key].componentInstance//使当前键最新鲜remove(keys,key)键。push(key)}else{//@doc如果不存在,存储缓存对象this.max)){//@doc超过最大数量,删除第一个pruneCacheEntry(cache,keys[0],keys,this._vnode)}}vnode.data.keepAlive=true}returnvnode||(slot&&slot[0])}}keep-aliverouter-view在router-view渲染组件时,会判断当前组件是否缓存。如果是缓存,直接使用缓存组件中的源码vue-router//@doc判断是否回keep-alive缓存if(vnodeData.keepAlive&&parent._inactive){inactive=true}//@doc如果组件被缓存,直接使用缓存中的组件if(inactive){returnh(cache[name],data,children)}