1.通过源码理解http层和tcp层的码仿码keep-alive
2.keep-alive的vue2和vue3的源码以及LRU算法
3.python题:随机密码生成。编写程序,小程序源在26个字母大小写和9个数字组成的码仿码列表中随机生成10个8位密码
4.彻底揭秘keep-alive
5.Vue3源码系列 (六) KeepAlive
6.Vue原理之keep-alive组件
通过源码理解http层和tcp层的keep-alive
理解HTTP层与TCP层的keep-alive机制是提升网络通信效率的关键。本文将通过源码解析,小程序源深入探讨如何在HTTP与TCP层实现keep-alive功能。码仿码
1.
HTTP层的小程序源ubbo 源码学习keep-alive
以nginx为例,解析HTTP报文时,码仿码若客户端发送了connection:keep-alive头,小程序源则nginx将维持此连接。码仿码配置中设定的小程序源过期时间与请求数限制,通过解析头信息与设置全局变量实现。码仿码
在解析HTTP头后,小程序源通过查找配置中的码仿码对应处理函数,进一步处理长连接。小程序源当处理完一个HTTP请求时,码仿码NGINX将连接状态标记为长连接,并设置相应标志。当连接达到配置的时间或请求数限制时,NGINX将关闭连接,释放资源。
2.
TCP层的keep-alive
TCP层提供的keep-alive功能更为全面,通过Linux内核配置进行调整。默认配置与阈值设定共同作用于keep-alive功能。
通过setsockopt函数可动态设置TCP层的keep-alive参数,实现不同场景下的keep-alive策略。超时处理通过系统内核函数完成,确保在长时间无数据传输时,能够及时释放资源,避免占用系统连接。
总结:HTTP层与TCP层的keep-alive机制通过不同方式实现长连接的维护与管理,有效提高了网络通信的效率与资源利用率。深入理解其源码实现,有助于在实际应用中更灵活地配置与优化网络连接策略。上班打卡网页源码
keep-alive的vue2和vue3的源码以及LRU算法
0.LRU算法
LRU(leastrecentlyused)根据数据的历史记录来淘汰数据,重点在于保护最近被访问/使用过的数据,淘汰现阶段最久未被访问的数据
LRU的主体思想在于:如果数据最近被访问过,那么将来被访问的几率也更高
经典的LRU实现一般采用双向链表+Hash表。借助Hash表来通过key快速映射到对应的链表节点,然后进行插入和删除操作。这样既解决了hash表无固定顺序的缺点,又解决了链表查找慢的缺点。
但实际上在js中无需这样实现,可以参考文章第三部分。先看vue的keep-alive实现。
1.keep-alivekeep-alive是vue中的内置组件,使用KeepAlive后,被包裹的组件在经过第一次渲染后的vnode会被缓存起来,然后再下一次再次渲染该组件的时候,直接从缓存中拿到对应的vnode进行渲染,并不需要再走一次组件初始化,render和patch等一系列流程,减少了script的执行时间,性能更好。
使用原则:当我们在某些场景下不需要让页面重新加载时我们可以使用keepalive
当我们从首页–>列表页–>商详页–>再返回,这时候列表页应该是需要keep-alive
从首页–>列表页–>商详页–>返回到列表页(需要缓存)–>返回到首页(需要缓存)–>再次进入列表页(不需要缓存),这时候可以按需来控制页面的keep-alive
在路由中设置keepAlive属性判断是否需要缓存。
2.vue2的实现实现原理:通过keep-alive组件插槽,获取第一个子节点。根据include、exclude判断是否需要缓存,通过组件的key,判断是否命中缓存。利用LRU算法,更新缓存以及对应的keys数组。根据max控制缓存的最大组件数量。
先看vue2的多宝菠菜源码实现:
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))})this.$watch('exclude',val=>{ pruneCache(this,name=>!matches(val,name))})},render(){ constslot=this.$slots.defaultconstvnode:VNode=getFirstComponentChild(slot)constcomponentOptions:?VNodeComponentOptions=vnode&&vnode.componentOptionsif(componentOptions){ //checkpatternconstname:?string=getComponentName(componentOptions)const{ include,exclude}=thisif(//notincluded(include&&(!name||!matches(include,name)))||//excluded(exclude&&name&&matches(exclude,name))){ returnvnode}const{ cache,keys}=thisconstkey:?string=vnode.key==null?componentOptions.Ctor.cid+(componentOptions.tag?`::${ componentOptions.tag}`:''):vnode.keyif(cache[key]){ vnode.componentInstance=cache[key].componentInstance//makecurrentkeyfreshestremove(keys,key)keys.push(key)}else{ cache[key]=vnodekeys.push(key)//pruneoldestentryif(this.max&&keys.length>parseInt(this.max)){ pruneCacheEntry(cache,keys[0],keys,this._vnode)}}vnode.data.keepAlive=true}returnvnode||(slot&&slot[0])}}可以看到<keep-alive>组件的实现也是一个对象,注意它有一个属性abstract为true,是一个抽象组件,它在组件实例建立父子关系的时候会被忽略,发生在initLifecycle的过程中:
//忽略抽象组件letparent=options.parentif(parent&&!options.abstract){ while(parent.$options.abstract&&parent.$parent){ parent=parent.$parent}parent.$children.push(vm)}vm.$parent=parent然后在?created?钩子里定义了?this.cache?和?this.keys,用来缓存已经创建过的?vnode。
<keep-alive>直接实现了render函数,执行<keep-alive>组件渲染的时候,就会执行到这个render函数,接下来我们分析一下它的实现。
首先通过插槽获取第一个子元素的vnode:
constslot=this.$slots.defaultconstvnode:VNode=getFirstComponentChild(slot)<keep-alive>只处理第一个子元素,所以一般和它搭配使用的有component动态组件或者是router-view。
然后又判断了当前组件的名称和include、exclude(白名单、黑名单)的关系:
//checkpatternconstname:?string=getComponentName(componentOptions)const{ include,exclude}=thisif(//notincluded(include&&(!name||!matches(include,name)))||//excluded(exclude&&name&&matches(exclude,name))){ returnvnode}functionmatches(pattern:string|RegExp|Array<string>,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)}returnfalse}组件名如果不满足条件,那么就直接返回这个组件的vnode,否则的话走下一步缓存:
const{ cache,keys}=thisconstkey:?string=vnode.key==null?componentOptions.Ctor.cid+(componentOptions.tag?`::${ componentOptions.tag}`:''):vnode.keyif(cache[key]){ vnode.componentInstance=cache[key].componentInstance//makecurrentkeyfreshestremove(keys,key)keys.push(key)}else{ cache[key]=vnodekeys.push(key)//pruneoldestentryif(this.max&&keys.length>parseInt(this.max)){ pruneCacheEntry(cache,keys[0],keys,this._vnode)}}如果命中缓存,则直接从缓存中拿vnode的组件实例,并且重新调整了key的顺序放在了最后一个;否则把vnode设置进缓存,如果配置了max并且缓存的长度超过了this.max,还要从缓存中删除第一个。
这里的实现有一个问题:判断是否超过最大容量应该放在put操作前。为什么呢?我们设置一个缓存队列,都已经满了你还塞进来?最好先删一个才能塞进来新的。
继续看删除缓存的实现:
functionpruneCacheEntry(cache:VNodeCache,key:string,keys:Array<string>,current?:VNode){ constcached=cache[key]if(cached&&(!current||cached.tag!==current.tag)){ cached.componentInstance.$destroy()}cache[key]=nullremove(keys,key)}除了从缓存中删除外,还要判断如果要删除的缓存的组件tag不是当前渲染组件tag,则执行删除缓存的组件实例的$destroy方法。
————————————
可以发现,vue实现LRU算法是通过Array+Object,数组用来记录缓存顺序,Object用来模仿Map的功能进行vnode的缓存(created钩子里定义的this.cache和this.keys)
2.vue3的实现vue3实现思路基本和vue2类似,这里不再赘述。主要看LRU算法的道歉用程序源码实现。
vue3通过set+map实现LRU算法:
constcache:Cache=newMap()constkeys:Keys=newSet()并且在判断是否超过缓存容量时的实现比较巧妙:
if(max&&keys.size>parseInt(maxasstring,)){ pruneCacheEntry(keys.values().next().value)}这里巧妙的利用Set是可迭代对象的特点,通过keys.value()获得包含keys中所有key的可迭代对象,并通过next().value获得第一个元素,然后进行删除。
3.借助vue3的思路实现LRU算法Leetcode题目——LRU缓存
varLRUCache=function(capacity){ this.map=newMap();this.capacity=capacity;};LRUCache.prototype.get=function(key){ if(this.map.has(key)){ letvalue=this.map.get(key);//删除后,再set,相当于更新到map最后一位this.map.delete(key);this.map.set(key,value);returnvalue;}return-1;};LRUCache.prototype.put=function(key,value){ //如果已经存在,那就要更新,即先删了再进行后面的setif(this.map.has(key)){ this.map.delete(key);}else{ //如果map中不存在,要先判断是否超过最大容量if(this.map.size===this.capacity){ this.map.delete(this.map.keys().next().value);}}this.map.set(key,value);};这里我们直接通过Map来就可以直接实现了。
而keep-alive的实现因为缓存的内容是vnode,直接操作Map中缓存的位置代价较大,而采用Set/Array来记录缓存的key来模拟缓存顺序。
参考:
LRU缓存-keep-alive实现原理
带你手撸LRU算法
Vue.js技术揭秘
原文;/post/python题:随机密码生成。编写程序,在个字母大小写和9个数字组成的列表中随机生成个8位密码
keep_words=['and','as','assert','break','class','continue','def','del','elif','else','except','finally',
'for','from','global','if','import','in','is',
'lambda','nonlocal','not','or','pass','raise',
'return','try','while','time','with','yield','True',
'False','None']
def upper_word(fname_tem,num,keep):
file_tem=open('{ }.py'.format(format(fname_tem)),'r',encoding='utf-8')
file_new=open('{ }_changed.py'.format(format(fname_tem)),'w',encoding='utf-8')
#逐行读取,逐行处理,逐行写入
for line in file_tem:
for word in keep_words:
if word in line:
num=num+1
keep['编号%s'%str(num)]=word
line=line.replace(word,'编号%s'%str(num))
else:
continue
line=line.upper()
for key in keep.keys():
if key in line:
line=line.replace(key,keep[key])
file_new.write(line)
file_tem.close()
file_new.close()
def main():
num=
keep={ }
fname_tem=input('请输入Python源代码文件名:')
upper_word(fname_tem,num,keep)
main()
扩展资料:
定义和用法
<input>标签用于搜集用户信息。
根据不同的type属性值,输入字段拥有很多种形式。输入字段可以是文本字段、复选框、掩码后的文本控件、单选按钮、按钮等等。
input()函数直接接受且不改变输入数据的类型,但是需要注意的是使用input()在输入字符串时需要添加引号,否则会报错。
<2>.end=''标明在end后面传递一个空字符串,这样print函数不会在字符串末尾添加一个换行符,而是添加一个空字符串,也就是外贸小程序源码说,它的意思是末尾不换行,加空格。
HTML与XHTML之间的差异
在HTML中,<input>标签没有结束标签。
在XHTML中,<input>标签必须被正确地关闭。
彻底揭秘keep-alive
深入剖析keep-alive的实现与应用,本文将详细讲解其背后的原理和使用场景。keep-alive组件在Vue中用于缓存不活动的组件实例,而非销毁它们,从而在动态路由切换时保存组件的状态,提升性能。
keep-alive的应用场景广泛,比如当用户在列表页面进行筛选后进入详情页面,再切换回列表页面时,希望筛选条件或选中状态保持不变。通过包裹列表组件于keep-alive内,可以避免组件重复渲染,优化用户体验和系统效率。
使用keep-alive的关键是理解其几个核心属性和功能,包括`include`、`exclude`及`max`。`include`指定了需要缓存的组件白名单,`exclude`则定义了不应缓存的黑名单,而`max`则设定了缓存组件的上限,超过此限制时,系统将使用LRU策略替换旧缓存。
深入源码,keep-alive组件内嵌于Vue生态体系中,它对外暴露了组件的基本生命周期钩子以及几个主要配置属性。抽象属性设置为`true`对于组件缓存机制至关重要,其对组件的处理方式不同于其他普通组件。
keep-alive的渲染机制与其他Vue组件存在差异。在初始化阶段,Vue实例与子组件建立父子关系时会考虑抽象属性的值。当组件设置为`abstract: true`时,即跳过了该组件实例的渲染过程,从而避免了实际DOM节点的生成。这一特性显著优化了缓存组件的性能表现。
当组件从缓存中被激活或进入活跃状态时,patch阶段执行了一系列操作,如`createComponent`函数实现了缓存组件的重新挂载过程。通过`keep-alive`属性的管理,组件在切换和返回时能够保持状态的一致性,而组件的重用机制使得在不同的渲染上下文中实现高效状态转换成为可能。
了解keep-alive的钩子函数机制对于其高效应用至关重要。`activated`与`deactivated`钩子分别对应组件状态变化的两种极端情况,其执行策略避免了不必要的渲染过程,进一步提高了应用性能和响应速度。
综上所述,掌握keep-alive的原理与应用能够显著优化Vue应用的性能与用户体验。通过对组件状态的缓存和智能管理,减少不必要的DOM操作,从而实现高效响应和流畅界面。
Vue3源码系列 (六) KeepAlive
KeepAlive组件用于缓存组件状态,它本身不渲染DOM元素或出现在父组件链中。适配单一组件使用,与component或router-view协同工作。
KeepAlive的核心实现为KeepAliveImpl。其包含组件名称、判断是否为KeepAlive的标记、属性类型和setup方法。KeepAlive与实例化渲染器通过上下文传递信息。在当前实例的上下文对象ctx中,暴露激活与去激活方法activate和deactivate。
在setup中,获取当前实例上下文并挂载activate和deactivate。激活时,通过patch方法对比更新,同步props变更,组件设为非去激活状态,调用实例的onActived钩子。去激活操作类似。组件卸载及销毁缓存方法在setup返回函数内实现。
使用watch API监控include、exclude变化,依据match函数筛选出缓存组件,用于销毁操作。onMounted、onUpdated、onBeforeUnmount安排缓存子组件树及组件onDeactived钩子调用,最后组件卸载。setup返回的函数确保只对插入的单个组件有效。
当rawVNode为默认插槽的第一个元素,直接返回组件,跳过缓存流程。异步组件返回rawVNode,缓存执行。若rawVNode未直接返回且非异步组件,则依据逻辑返回组件或执行缓存程序。
KeepAlive组件实质即KeepAliveImpl,重申类型。onActived和onDeactived生命周期钩子通过registerKeepAliveHook注册。此函数包装钩子并注入KeepAlive,确保遍历组件树时仅查找KeepAlive中的钩子列表,组件卸载时移除相应钩子。
Vue原理之keep-alive组件
Vue原理解析:keep-alive组件的运用与机制
Vue内置的keep-alive组件旨在实现组件的智能缓存,当页面间切换时,非活动组件会被保留而非销毁,以保持用户状态的连续性。例如,当从页面A跳转到B,若使用keep-alive,再次返回A时,搜索框的输入将被保留。 如何运用keep-alive呢?它提供了三个内置属性,允许精确控制哪些组件缓存和哪些不缓存,以及设定缓存组件的最大数量。同时,它还提供了两个特殊生命周期钩子,仅在组件被keep-alive包裹时触发,但在2.1.0版本之后,若排除组件则不受影响,且在服务端渲染中也无效。初次加载时,created、mounted和activated会被依次触发,退出时调用deactivated,再次进入时仅触发activated。 深入了解keep-alive的原理,我们从源码出发。其核心包括三个步骤:首先,根据render中的vnodeToCache判断并缓存组件,构建数据结构并存储在cache数组和keys数组中。然后,检查是否达到最大缓存限制,如有则清理超出部分。最后,监听include和exclude的变动,相应地销毁对应的组件。Vue 全站缓存之 keep-alive : 动态移除缓存
本文将探讨如何在 Vue 开发项目中实现全站缓存的动态管理,特别关注如何解决 keep-alive 组件在页面切换时的缓存问题。通常情况下,Vue 开发者会使用 Vuex 或 localStorage 进行页面间的数据存储与调用。然而,这种做法并不科学且缺乏优雅性。keep-alive 组件提供了一种保留组件实例的方法,但默认情况下,所有组件数据均被保留,这在用户前进操作时形成障碍。为了解决此问题,本文提出并实施了一个解决方案,通过直接操作 keep-alive 组件内部的缓存列表,实现组件的动态销毁,进而解决缓存问题。
在文章开头,我们引入了一个记账项目的例子,以说明页面间互动行为的两种情况:用户前进和后退。keep-alive 组件在后退时能有效保留数据,但在前进时则无法实现进入新页面的预期效果。为解决这一问题,官方提供了 include 和 exclude 特性,允许开发者自定义哪些页面使用缓存。然而,这并没有解决如何根据需求灵活使用缓存的问题。因此,有人提出了在离开页面时销毁该页面的想法,但实验证明此法存在组件销毁而缓存仍存在的 bug。
为解决这个问题,开发者研究了 keep-alive 的源代码,并在其中寻找了一个关键点:在组件销毁时判断其是否已被缓存,进而决定是否使用缓存。然而,这一尝试并未获得通过。因此,开发者转向寻找其他解决方案,并在打印组件变量的过程中发现了 keep-alive 组件的 cache 列表。通过在组件销毁前直接操作此列表,实现缓存的动态删除,问题迎刃而解。
本文提出的解决方案提供了一种直接且暴力的方法,即在组件销毁前,寻找对应路由组件的 keep-alive 组件,然后控制其 cache 列表,以强制删除缓存。通过这一手段,可以有效解决 keep-alive 组件在页面切换时的缓存问题。文章最后,作者强调了 keep-alive 默认不支持动态销毁缓存的限制,并指出了解决方案的局限性。同时,作者预告了后续文章将深入讨论如何在前后页之间进行数据传递的解决方案。