vue单页缓存方案的分析与实现
要实现全站页面缓存,向前刷新,返回缓存,记住上一页的滚动位置,参考很多技术实现。在github上实现导航组件的原理要么使用keep-alive,要么引用keep-alive的源代码,但是只有keep-alive不能实现同一个路径,不同的参数显示不同的视图,有点坑坑洼洼。因此,有必要结合要实现的功能,适当转换保活。为了实现刷新每一次前进、返回缓存、自动定位的功能,文章从以下几个方面入手:两套技术方案可选、最终技术方案的原因、实现的功能和原理、被踩过的坑。
方案vue的保活组件
具体用途如下:
保持活动状态max=' 10 '路由器-视图//保持活动状态。为什么用这种方式?
例如,vue官网(https://cn.vuejs.org/v2/api/#keep-alive)介绍:
当保活包装动态组件时,它缓存非活动组件实例,而不是销毁它们。像transition一样,keep-alive是一个抽象组件:它不会自己呈现一个DOM元素,也不会出现在父组件链中。
当一个组件被切换到保持活动状态时,其激活和停用的生命周期挂钩功能将被相应地执行。主要用于保存组件状态或避免重新渲染。
因为在切换页面时通常需要缓存,所以需要结合vue路由器的路由器视图来实现
为什么保活可以实现缓存?
render () { const slot=this。$ slots . default const VNode : VNode=getfirst component child(插槽)const componentOptions:vnode component options=vnode vnode.component options if(component options){//检查模式常量名称:string=getcomponent name(component options)const { include,exclude }=this if (//不包含(include(!名称||!匹配(包括,名称)))|| //排除(排除名称匹配(排除,名称))){返回vnode } const { cache,keys }=这个const key:string=vnode.key==null //相同的构造函数可能会注册为不同的本地组件//因此仅cid是不够的(#3269)?组件选项。Ctor.cid (componentOptions.tag?` : $ { ComponentOptions . tag } ` : ' '): vnode . key if(cache[key]){ vnode . ComponentInstance=cache[key]。componentInstance //使当前键最新鲜remove(keys,key)keys . push(key)} else { cache[key]=vnode keys . push(key)//如果(this . max keys . length ParSeint(this . max)){ pre cacheentry(cache,keys [0],keys,this。_ vnode)} } vnode . data . keepalive=true } return vnode | |(slot slot[0])}是如上所示的keepalive源代码。渲染功能实现如下:获得要渲染的尝试组件作为槽内容;在渲染路径匹配的视图组件时,会根据vnode中存储的内容获取对应的名称,这些组件实例会放入变量缓存一次,这样就可以根据路由找到缓存的vnode,并返回createComponent方法执行initComponent。vue组件渲染这段的代码如下
函数initComponent (vnode,insertedvnode queue){ if(isDef(vnode . data . pending insert)){ insertedvnode queue . push . apply(insertedvnode queue,vnode . data . pending insert)vnode . data . pending insert=null } vnode . elm=vnode.component instance . $ El if(isPatchable(vnode)){ invokeCreateHooks(vnode,insertedvnode queue)setScope(vnode)} else {//空组件根。//跳过除ref (#3455) registerRef(vnode)之外的所有元素相关模块//确保调用insert hook inserted node due . push(vnode)} }将有vnode.elm缓存由vnode创建的DOM节点。因此,对于第一次渲染,除了在保活中构建缓存之外,与普通组件渲染没有什么不同。从输入到返回的一般执行流程如下
可以实现的功能
要缓存的组件呈现的vnode可以记录在缓存中,返回时可以由缓存中的dom直接呈现,保活组件提供的include和exclude属性可以有条件地缓存要缓存的组件。如果配置了最大值,并且缓存长度超过该最大值,则应从缓存中删除第一个值。
存在的问题
存在的问题是存储vnode节点的关键是name,这是定义路由时组件对应的名称,会导致路径相同。当打开不同的参数时,从缓存中获得的vnode将呈现相同的视图。但是很多业务场景根据参数显示不同的内容,但是保活底层并没有对此进行扩展,可以看看保活源代码。
const key:string=vnode.key==null?组件选项。Ctor.cid (componentOptions.tag?` : $ { ComponentOptions . tag } ` : ' '): vnode . key if(cache[key]){ vnode . ComponentInstance=cache[key]。componentInstance //使当前键最新鲜remove(keys,key)keys . push(key)} else { cache[key]=vnode keys . push(key)//如果(this . max keys . length ParSeint(this . max)){ pre cacheentry(cache,keys [0],keys,this。_ vnode)}} vnode.key是路由中定义的名称,所以要用这个方案实现根据不同参数显示不同视图的功能,这里需要对key进行改造,但是keep-alive是vue自己的,底层是不能改变的,然后我的第二个方案就诞生了。
方案2:导航组件,scrollbehavior
github上有一个功能类似的组件vue-navigation。该vue组件可以实现返回到行走缓存。基本原理与保活相同。事实上,keep-alive组件被重写,并且在正向刷新过程中添加了一个参数VNK,这样当路由发生变化时,它就会给url带来一个参数,而cache的键值就取决于这个参数。借鉴这个组件的思想,制作了一个类似keep-alive的组件,其中key的值是通过getKey方法获取的,重写后的渲染方法如下
render () { var vnode=this。$slots.default?这个。$ slots . default[0]: null if(vnode){ vnode . key=vnode . key | |(vnode . iscomment?comment ' : vnode . tag)const { cache,keys }=this var key=getKey(this。$route,KeyName)if(vnode . key . indexof(key)===-1){ vnode . key=' _ _ navigation-' key '-' vnode . key } if(cache[key]){ if(vnode . key===cache[key]。key){ vnode.component instance=cache[key]。component instance } else { cache[key].component instance . $ destroy()cache[key]=vnode } remove(keys,key)keys . push(key)} else { cache[key]=vnode keys . push(key)//修剪最旧的条目if(this . max keys . length parseInt(this . max)){修剪缓存条目(cache,keys [0],keys,this。_ vnode)} } vnode . data . keepalive=true }返回vnode} getkey方法实现
//将参数vnk的值添加到//url,导出函数genkey(){//const t t='
版权声明:vue单页缓存方案的分析与实现是由宝哥软件园云端程序自动收集整理而来。如果本文侵犯了你的权益,请联系本站底部QQ或者邮箱删除。