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

Vue保活源码分析

时间:2023-04-01 12:22:28 vue.js

1.道具:包括保持活动组件-字符串或正则表达式。只有具有匹配名称的组件才会被缓存。exclude-字符串或正则表达式。名称匹配的任何组件都不会被缓存。最大值-一个数字。可以缓存的最大组件实例数。2.keep-alive是vue的内置组件。所有组件都可以通过components获取keep-alive组件选项(内置组件以原型的形式保存在components对象上,而不是直接保存在组件上),根据获取到的组件选项创建keep-alive组件。//保持活动组件选项varKeepAlive={name:'keep-alive',abstract:true,//抽象组件props:{...},created:functioncreated(){this.cache=Object.create(null);//缓存组件this.keys=[];//缓存组件ID},mounted:{...},render:{...}};3.keep-alive组件在调用render函数时渲染页面,首先获取keep-alive组件标签中的组件标签节点(默认slot生成的节点,VNode实例)。然后根据组件名称判断该节点是否满足缓存条件,如果不满足则直接返回该节点,否则判断该节点是否已经被缓存。如果已经缓存,直接读取之前缓存的组件(Vue实例),保存到当前节点,然后返回到当前节点。如果没有缓存,则在返回前缓存当前节点。缓存的内容是组件,组件本身包含数据状态,页面是根据数据渲染的,所以组件激活时可以保持之前的状态。//keep-aliverenderfunctionrender:functionrender(){varslot=this.$slots.default;//获取组件中的标签节点varvnode=getFirstComponentChild(slot);varcomponentOptions=vnode&&vnode.componentOptions;if(componentOptions){//检查模式varname=getComponentName(componentOptions);//获取组件名称varref=this;varinclude=ref.include;varexclude=ref.exclude;if(//不包含(include&&(!name||!matches(include,name)))||//nonameininclude//exclude(exclude&&name&&matches(exclude,name))//namein排除){返回vnode;//没有缓存直接返回}varref$1=this;varcache=ref$1.cache;varkeys=ref$1.keys;varkey=vnode.key==null?//相同的构造函数可能会注册为不同的本地组件//所以仅cid是不够的(#3269)componentOptions.Ctor.cid+(componentOptions.tag?"::"+componentOptions.tag:""):vnode.key;if(cache[key]){//直接读取缓存组件vnode.componentInstance=cache[key].componentInstance;//使当前键最新鲜remove(keys,key);键.推(键);}else{//添加组件缓存cache[key]=vnode;键.推(键);//剪掉最旧的条目if(this.max&&keys.length>parseInt(this.max)){//超过最大数量限制,销毁第一个被替换的节点实例(当max为0的字符串时,会报错报告)pruneCacheEntry(缓存,键[0],键,this._vnode);}}vnode.data。保活=真;//组件缓存标识符,保证组件不被销毁}returnvnode||(slot&&slot[0]);}4.当缓存组件被激活时(节点DOM插入页面),激活组件生命周期函数被调用当缓存组件标签被切换,组件节点被销毁,由于组件节点标识keepAlive为true,所以不会调用$destory销毁组件,而是冻结组件并触发去激活组件生命周期函数,同时移除组件对应的DOM从文档中删除。//节点生命周期varcomponentVNodeHooks={...insert:functioninsert(vnode){varcontext=vnode.context;varcomponentInstance=vnode.componentInstance;如果(!componentInstance._isMounted){componentInstance._isMounted=true;callHook(componentInstance,'mounted');//插入到DOM后触发}if(vnode.data.keepAlive){if(context._isMounted){//vue-router#1212//在更新期间,一个keep-alive组件的子组件可能会//??发生变化,因此直接在此处遍历树可能会在不正确的子组件上调用激活的挂钩。相反,我们将它们推入一个队列,//在整个补丁过程结束后进行处理。queueActivatedComponent(组件实例);}else{activateChildComponent(componentInstance,true/*direct*/);//激活组件}}},...destroy:functiondestroy(vnode){//节点销毁时的生生命周期数varcomponentInstance=vnode.componentInstance;if(!componentInstance._isDestroyed){if(!vnode.data.keepAlive){//不是keep-alive中的封装组件componentInstance.$destroy();}else{deactivateChildComponent(componentInstance,true/*直接*/);}}}};//激活组件functionactivateChildComponent(vm,direct){if(direct){vm._directInactive=false;if(isInInactiveTree(vm)){return}}elseif(vm._directInactive){return}if(vm._inactive||vm._inactive===null){vm._inactive=false;for(vari=0;i

最新推荐
猜你喜欢