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

保活使用及详解

时间:2023-04-01 00:52:15 vue.js

1.使用场景是一个列表页,数据量很大。我们选择过滤条件后,选择一条数据进入详情页。返回列表页后,我们希望保留原来的搜索结果。2.属性包括——字符串或正则表达式。只有具有匹配名称的组件才会被缓存。exclude-字符串或正则表达式。名称匹配的任何组件都不会被缓存。最大值-一个数字。可以缓存的最大组件实例数。3.了解keep-alive官网的例子:https://cn.vuejs.org/v2/guide...你会发现,如果你选择了一篇文章,切换到Archive标签,然后切换回Posts,将不会继续显示您之前选择的文章。这是因为每次切换到新选项卡时,Vue都会创建一个新的currentTabComponent实例。为了从Archive切换回Posts并保留原来选中的文章,我们可以使用keep-alivekeep-alive的使用方法(一)动态组件中使用(2)在路由组件中使用/keep-alive>4。keep-alive原理分析//src/core/components/keep-alive.jsexportdefault{name:'keep-alive',abstract:true,//判断当前组件的虚拟dom是否渲染为真实dom的关键props:{include:patternTypes,//缓存白名单exclude:patternTypes,//缓存黑名单max:[String,Number]//缓存的组件},created(){this.cache=Object.create(null)//cachevirtualdomthis.keys=[]//缓存虚拟dom的key集合},destroyed(){for(constkeyinthis.cache){//删除所有缓存pruneCacheEntry(this.cache,key,this.keys)}},mounted(){//实时监控黑白名单变化this.$watch('include',val=>{pruneCache(this,name=>matched(val,name))})this.$watch('exclude',val=>{pruneCache(this,name=>!matches(val,name))})},render(){//先省略...}}created:初始化两个对象缓存VNode(VirtualDOM)和VNode对应的key集合被销毁:删除缓存在this.cache中的VNode实例我们注意到,这并不是简单的将this.cache设置为null,而是遍历并调用pruneCacheEntry函数进行删除。//src/core/components/keep-alive.jsfunctionpruneCacheEntry(cache:VNodeCache,key:string,keys:Array,current?:VNode){constcached=cache[key]if(缓存&&(!current||cached.tag!==current.tag)){cached.componentInstance.$destroyed()//实现组件的销毁钩子函数}cache[key]=nullremove(keys,key)}删除缓存的VNode挂载组件实例对应的destroy钩子函数:在挂载的钩子中,监听include和exclude参数,然后实时更新(删除)this.cache对象数据。pruneCache函数的核心是调用pruneCacheEntry.functionpruneCache(keepAliveInstance:any,filter:Function){const{cache,keys,_vnode}=keepAliveInstancefor(constkeyincache){constcachedNode:?VNode=cache[key]if(cachedNode){constname:?string=getComponentName(cachedNode.componentOptions)if(name&&!filter(name)){pruneCacheEntry(cache,key,keys,_vnode)}}}}render:render(){constslot=this.$slots.defalutconstvnode:VNode=getFirstComponentChild(slot)//找到第一个子组件对象constcomponentOptions:?VNodeComponentOptions=vnode&&vnode.componentOptionsif(componentOptions){//组件参数存在//检查模式constname:?string=getComponentName(componentOptions)//组件名称const{include,exclude}=thisif(//条件匹配//不包含(include&&(!name||!matches(include,name)))||//排除(排除&&名称&&匹配(排除ude,name))){returnvnode}const{cache,keys}=this//定义组件的缓存键constkey:?string=vnode.key===null?componentOptions.Ctor.cid+(componentOptions.tag?`::${componentOptions.tag}`:''):vnode.keyif(cache[key]){//组件已经被缓存vnode.componentInstance=cache[key].componentInstanceremove(keys,key)keys.push(key)//调整键排序}else{cache[key]=vnode//缓存组件对象keys.push(key)if(this.max&&keys.length>parseInt(this.max)){//如果超过缓存个数,则删除第一个。pruneCacheEntry(cahce,keys[0],keys,this._vnode)}}vnode.data.keepAlive=true//渲染执行被包裹组件的钩子函数需要}returnvnode||(slot&&slot[0])}第一步:获取第一个被keep-alive包裹的子组件对象及其组件名称;第二步:根据设置的黑白名单进行条件(如果有)匹配,判断缓存是否匹配,直接返回组件实例(VNode),否则执行第三步;第三步:根据组件ID和tag生成缓存key,检查缓存对象中是否缓存了组件实例。如果存在,则直接取出缓存值并更新key在this.keys中的位置(更新key的位置是实现LRU替换策略的关键),否则执行第四步;第四步:将key存入this.cache对象Component实例并保存key值,然后检查缓存的实例数是否超过max设置值,如果超过则删除最新最长未使用的实例(即是,根据LRU替换策略下标为0)的key;第5步:最后,将组件实例的keepAlive属性值设置为true非常重要。keep-alive不会生成真正的DOM节点//src/core/instance/lifecycle.jsexportfunctioninitLifecycle(vm:Component){constoptions=vm.$options//寻找第一个非抽象父组件实例letparent=options.parentif(parent&&!options.abstract){while(parent.$options.abstract&&parent.$parent){parent=parent.$parent}parent.$children.push(vm)}vm.$parent=parent//...}Vue在初始化生命周期时,为组件实例建立父子关系,会根据抽象属性决定是否忽略组件。在keep-alive中,如果设置了abstract:true,Vue将跳过组件实例。最后构建的组件树不会包含keep-alive组件,所以组件树渲染的DOM树自然不会有keep-alive相关节点。5.使用keep-alive踩坑include是根据name判断的,需要给组件赋name值,否则不会生效(本地生效,部署后不生效)参考:https://万维网。jianshu.com/p/952…