发布网友 发布时间:2024-09-30 11:22
共1个回答
热心网友 时间:2024-10-06 13:38
1、通过本文可以了解到vue3keepalive功能
2、通过本文可以了解到vue3keepalive使用场景
3、通过本文可以学习到vue3keepalive真实的使用过程
4、通过本文可以学习vue3keepalive源码调试
5、通过本文可以学习到vue3keepalive源码的精简分析
1、keepalive功能keepalive是vue3中的一个全局组件
keepalive本身不会渲染出来,也不会出现在dom节点当中,但是它会被渲染为vnode,通过vnode可以跟踪到keepalive中的cache和keys,当然也是在开发环境才可以,build打包以后没有暴露到vnode中(这个还要再确认一下)
keepalive最重要的功能就是缓存组件
keepalive通过LRU缓存淘汰策略来更新组件缓存,可以更有效的利用内存,防止内存溢出,源代码中的最大缓存数max为10,也就是10个组件之后,就开始淘汰最先被缓存的组件了
2、keepalive使用场景这里先假设一个场景:A页面是首页=====>B页面列表页面(需要缓存的页面)=======>C详情页由C详情页到到B页面的时候,要返回到B的缓存页面,包括页面的基础数据和列表的滚动条位置信息如果由B页面返回到A页面,则需要将B的缓存页清空
上述另外一个场景:进入页面直接缓存,然后就结束了,这个比较简单本文就不讨论了
3、在项目中的使用过程keepalive组件总共有三个参数
include:可传字符串、正则表达式、数组,名称匹配成功的组件会被缓存
exclude:可传字符串、正则表达式、数组,名称匹配成功的组件不会被缓存
max:可传数字,限制缓存组件的最大数量,默认为10
首先在App.vue根代码中添加引入keepalive组件,通过这里可以发现,我这里缓存的相当于整个页面,当然你也可以进行更细粒度的控制页面当中的某个区域组件
<template><router-viewv-slot="{Component}"><keep-alive:include="keepAliveCache"><component:is="Component":key="$route.name"/></keep-alive></router-view></template><scriptlang="ts"setup>import{computed}from"vue";import{useKeepAliverStore}from"@/store";constuseStore=useKeepAliverStore();constkeepAliveCache=computed(()=>{returnuseStore.caches;});</script>通过App.vue可以发现,通过pinia(也就是vue2中使用的vuex)保存要缓存的页面组件,来处理include缓存,和保存页面组件中的滚动条信息数据
import{defineStore}from"pinia";exportconstuseKeepAliverStore=defineStore("useKeepAliverStore",{state:()=>({caches:[]asany,scrollList:newMap(),//缓存页面组件如果又滚动条的高度}),actions:{add(name:string){this.caches.push(name);},remove(name:string){console.log(this.caches,'this.caches')this.caches=this.caches.filter((item:any)=>item!==name);console.log(this.caches,'this.caches')},clear(){this.caches=[]}}});组件路由刚刚切换时,通过beforeRouteEnter将组件写入include,此时组件生命周期还没开始。如果都已经开始执行组件生命周期了,再写入就意义了。所以这个钩子函数就不能写在setup中,要单独提出来写。当然你也可以换成路由的其他钩子函数处理beforeEach,但这里面使用的话,好像使用不了pinia,这个还需要进一步研究一下。
import{useRoute,useRouter,onBeforeRouteLeave}from"vue-router";import{useKeepAliverStore}from"@/store";constuseStore=useKeepAliverStore()exportdefault{name:"record-month",beforeRouteEnter(to,from,next){next(vm=>{if(from.name==='Home'&&to.name==='record-month'){useStore.add(to.name)}});}}</script>组件路由离开时判断,是否要移出缓存,这个钩子就直接写在setup中就可以了。
onBeforeRouteLeave((to,from)=>{console.log(to.name,"onBeforeRouteLeave");if(to.name==="new-detection-detail"){console.log(to,from,"进入详情页面不做处理");}else{useStore.remove(from.name)console.log(to,from,"删除组件缓存");}});在keepalive两个钩子函数中进行处理scroll位置的缓存,onActivated中获取缓存中的位置,onDeactivated记录位置到缓存
onActivated(()=>{if(useStore.scrollList.get(routeName)){consttop=useStore.scrollList.get(routeName)refList.value.setScrollTop(Number(top))}});onDeactivated(()=>{consttop=refList.value.getScrollTop()useStore.scrollList.set(routeName,top)});这里定义一个方法,设置scrollTop使用了原生javascript的api
constsetScrollTop=(value:any)=>{constdom=document.querySelector('.van-pull-refresh')dom!.scrollTop=value}同时高度怎么获取要先注册scroll事件,然后通过getScrollTop获取当前滚动条的位置进行保存即可
onMounted(()=>{scrollDom.value=document.querySelector('.van-pull-refresh')asHTMLElementconstthrottledFun=useThrottleFn(()=>{console.log(scrollDom.value?.scrollTop,'addEventListener')state.scrollTop=scrollDom.value!.scrollTop},500)if(scrollDom.value){scrollDom.value.addEventListener('scroll',throttledFun)}})constgetScrollTop=()=>{console.log('scrollDom.vaue',scrollDom.value?.scrollTop)returnstate.scrollTop}上面注册scroll事件中使用了一个useThrottleFn,这个类库是@vueuse/core中提供的,其中封装了很多工具都非常不错,用兴趣的可以研究研究
https://vueuse.org/shared/usethrottlefn/#usethrottlefn此时也可以查看找到实例的vnode查找到keepalive,是在keepalive紧挨着的子组件里
constinstance=getCurrentInstance()console.log(instance.vnode.parent)//这里便是keepalive组件vnode//如果是在开发环境中可以查看到cache对象instance.vnode.parent.__v_cache//vue源码中,在dev环境对cache进行暴露,生产环境是看不到的if(__DEV__||__FEATURE_PROD_DEVTOOLS__){;(instanceasany).__v_cache=cache}4、vue3keepalive源码调试1、克隆代码
gitclonegit@github.com:vuejs/core.git2、安装依赖
import{defineStore}from"pinia";exportconstuseKeepAliverStore=defineStore("useKeepAliverStore",{state:()=>({caches:[]asany,scrollList:newMap(),//缓存页面组件如果又滚动条的高度}),actions:{add(name:string){this.caches.push(name);},remove(name:string){console.log(this.caches,'this.caches')this.caches=this.caches.filter((item:any)=>item!==name);console.log(this.caches,'this.caches')},clear(){this.caches=[]}}});03、如果不能使用pnpm,可以先通过npm安装一下
import{defineStore}from"pinia";exportconstuseKeepAliverStore=defineStore("useKeepAliverStore",{state:()=>({caches:[]asany,scrollList:newMap(),//缓存页面组件如果又滚动条的高度}),actions:{add(name:string){this.caches.push(name);},remove(name:string){console.log(this.caches,'this.caches')this.caches=this.caches.filter((item:any)=>item!==name);console.log(this.caches,'this.caches')},clear(){this.caches=[]}}});14、安装完成以后,找到根目录package.json文件中的scripts
参考https://juejin.cn/post/6991653445161713671
import{defineStore}from"pinia";exportconstuseKeepAliverStore=defineStore("useKeepAliverStore",{state:()=>({caches:[]asany,scrollList:newMap(),//缓存页面组件如果又滚动条的高度}),actions:{add(name:string){this.caches.push(name);},remove(name:string){console.log(this.caches,'this.caches')this.caches=this.caches.filter((item:any)=>item!==name);console.log(this.caches,'this.caches')},clear(){this.caches=[]}}});25、执行pnpmrundev则会buildvue源码
import{defineStore}from"pinia";exportconstuseKeepAliverStore=defineStore("useKeepAliverStore",{state:()=>({caches:[]asany,scrollList:newMap(),//缓存页面组件如果又滚动条的高度}),actions:{add(name:string){this.caches.push(name);},remove(name:string){console.log(this.caches,'this.caches')this.caches=this.caches.filter((item:any)=>item!==name);console.log(this.caches,'this.caches')},clear(){this.caches=[]}}});36、然后在....\core\packages\vue\examples\composition中添加一个aehyok.html文件,将如下代码进行拷贝,然后通过chrome浏览器打开,F12,找到源代码的Tab页面,通过快捷键Ctrl+P输入KeepAlive便可以找到这个组件,然后通过左侧行标右键就可以添加断点,进行调试,也可以通过右侧的【调用堆栈】进行快速跳转代码进行调试。
import{defineStore}from"pinia";exportconstuseKeepAliverStore=defineStore("useKeepAliverStore",{state:()=>({caches:[]asany,scrollList:newMap(),//缓存页面组件如果又滚动条的高度}),actions:{add(name:string){this.caches.push(name);},remove(name:string){console.log(this.caches,'this.caches')this.caches=this.caches.filter((item:any)=>item!==name);console.log(this.caches,'this.caches')},clear(){this.caches=[]}}});47、调试源码发现keepalive中的render函数(或者说时setup中的return函数)在子组件切换时就会去执行,变更逻辑缓存
第一次进入页面初始化keepalive组件会执行一次,
然后点击组件一,再次执行render函数
然后点击组件二,会再次执行render函数
8、调试截图说明
9、调试操作,小视频观看
5、vue3keealive源码粗浅分析通过查看vue3KeepAlive.ts源码,源码路径:https://github.com/vuejs/core/blob/main/packages/runtime-core/src/components/KeepAlive.ts
import{defineStore}from"pinia";exportconstuseKeepAliverStore=defineStore("useKeepAliverStore",{state:()=>({caches:[]asany,scrollList:newMap(),//缓存页面组件如果又滚动条的高度}),actions:{add(name:string){this.caches.push(name);},remove(name:string){console.log(this.caches,'this.caches')this.caches=this.caches.filter((item:any)=>item!==name);console.log(this.caches,'this.caches')},clear(){this.caches=[]}}});56、总结通过这次查看vue3keepalive源码发现,其实也没那么难,当然这次查看源代码也只是粗略查看,并没有看的那么细,主要还是先解决问题。动动手调试一下,有时候真的就是不逼一下自己都不知道自己有多么的优秀。原来我也能稍微看看源代码了。以后有空可以多看看vue3源代码,学习一下vue3的精髓。了解vue3更为细节的一些知识点。
原文:https://juejin.cn/post/7103405860449157134热心网友 时间:2024-10-06 13:38
1、通过本文可以了解到vue3keepalive功能
2、通过本文可以了解到vue3keepalive使用场景
3、通过本文可以学习到vue3keepalive真实的使用过程
4、通过本文可以学习vue3keepalive源码调试
5、通过本文可以学习到vue3keepalive源码的精简分析
1、keepalive功能keepalive是vue3中的一个全局组件
keepalive本身不会渲染出来,也不会出现在dom节点当中,但是它会被渲染为vnode,通过vnode可以跟踪到keepalive中的cache和keys,当然也是在开发环境才可以,build打包以后没有暴露到vnode中(这个还要再确认一下)
keepalive最重要的功能就是缓存组件
keepalive通过LRU缓存淘汰策略来更新组件缓存,可以更有效的利用内存,防止内存溢出,源代码中的最大缓存数max为10,也就是10个组件之后,就开始淘汰最先被缓存的组件了
2、keepalive使用场景这里先假设一个场景:A页面是首页=====>B页面列表页面(需要缓存的页面)=======>C详情页由C详情页到到B页面的时候,要返回到B的缓存页面,包括页面的基础数据和列表的滚动条位置信息如果由B页面返回到A页面,则需要将B的缓存页清空
上述另外一个场景:进入页面直接缓存,然后就结束了,这个比较简单本文就不讨论了
3、在项目中的使用过程keepalive组件总共有三个参数
include:可传字符串、正则表达式、数组,名称匹配成功的组件会被缓存
exclude:可传字符串、正则表达式、数组,名称匹配成功的组件不会被缓存
max:可传数字,限制缓存组件的最大数量,默认为10
首先在App.vue根代码中添加引入keepalive组件,通过这里可以发现,我这里缓存的相当于整个页面,当然你也可以进行更细粒度的控制页面当中的某个区域组件
<template><router-viewv-slot="{Component}"><keep-alive:include="keepAliveCache"><component:is="Component":key="$route.name"/></keep-alive></router-view></template><scriptlang="ts"setup>import{computed}from"vue";import{useKeepAliverStore}from"@/store";constuseStore=useKeepAliverStore();constkeepAliveCache=computed(()=>{returnuseStore.caches;});</script>通过App.vue可以发现,通过pinia(也就是vue2中使用的vuex)保存要缓存的页面组件,来处理include缓存,和保存页面组件中的滚动条信息数据
import{defineStore}from"pinia";exportconstuseKeepAliverStore=defineStore("useKeepAliverStore",{state:()=>({caches:[]asany,scrollList:newMap(),//缓存页面组件如果又滚动条的高度}),actions:{add(name:string){this.caches.push(name);},remove(name:string){console.log(this.caches,'this.caches')this.caches=this.caches.filter((item:any)=>item!==name);console.log(this.caches,'this.caches')},clear(){this.caches=[]}}});组件路由刚刚切换时,通过beforeRouteEnter将组件写入include,此时组件生命周期还没开始。如果都已经开始执行组件生命周期了,再写入就意义了。所以这个钩子函数就不能写在setup中,要单独提出来写。当然你也可以换成路由的其他钩子函数处理beforeEach,但这里面使用的话,好像使用不了pinia,这个还需要进一步研究一下。
import{useRoute,useRouter,onBeforeRouteLeave}from"vue-router";import{useKeepAliverStore}from"@/store";constuseStore=useKeepAliverStore()exportdefault{name:"record-month",beforeRouteEnter(to,from,next){next(vm=>{if(from.name==='Home'&&to.name==='record-month'){useStore.add(to.name)}});}}</script>组件路由离开时判断,是否要移出缓存,这个钩子就直接写在setup中就可以了。
onBeforeRouteLeave((to,from)=>{console.log(to.name,"onBeforeRouteLeave");if(to.name==="new-detection-detail"){console.log(to,from,"进入详情页面不做处理");}else{useStore.remove(from.name)console.log(to,from,"删除组件缓存");}});在keepalive两个钩子函数中进行处理scroll位置的缓存,onActivated中获取缓存中的位置,onDeactivated记录位置到缓存
onActivated(()=>{if(useStore.scrollList.get(routeName)){consttop=useStore.scrollList.get(routeName)refList.value.setScrollTop(Number(top))}});onDeactivated(()=>{consttop=refList.value.getScrollTop()useStore.scrollList.set(routeName,top)});这里定义一个方法,设置scrollTop使用了原生javascript的api
constsetScrollTop=(value:any)=>{constdom=document.querySelector('.van-pull-refresh')dom!.scrollTop=value}同时高度怎么获取要先注册scroll事件,然后通过getScrollTop获取当前滚动条的位置进行保存即可
onMounted(()=>{scrollDom.value=document.querySelector('.van-pull-refresh')asHTMLElementconstthrottledFun=useThrottleFn(()=>{console.log(scrollDom.value?.scrollTop,'addEventListener')state.scrollTop=scrollDom.value!.scrollTop},500)if(scrollDom.value){scrollDom.value.addEventListener('scroll',throttledFun)}})constgetScrollTop=()=>{console.log('scrollDom.vaue',scrollDom.value?.scrollTop)returnstate.scrollTop}上面注册scroll事件中使用了一个useThrottleFn,这个类库是@vueuse/core中提供的,其中封装了很多工具都非常不错,用兴趣的可以研究研究
https://vueuse.org/shared/usethrottlefn/#usethrottlefn此时也可以查看找到实例的vnode查找到keepalive,是在keepalive紧挨着的子组件里
constinstance=getCurrentInstance()console.log(instance.vnode.parent)//这里便是keepalive组件vnode//如果是在开发环境中可以查看到cache对象instance.vnode.parent.__v_cache//vue源码中,在dev环境对cache进行暴露,生产环境是看不到的if(__DEV__||__FEATURE_PROD_DEVTOOLS__){;(instanceasany).__v_cache=cache}4、vue3keepalive源码调试1、克隆代码
gitclonegit@github.com:vuejs/core.git2、安装依赖
import{defineStore}from"pinia";exportconstuseKeepAliverStore=defineStore("useKeepAliverStore",{state:()=>({caches:[]asany,scrollList:newMap(),//缓存页面组件如果又滚动条的高度}),actions:{add(name:string){this.caches.push(name);},remove(name:string){console.log(this.caches,'this.caches')this.caches=this.caches.filter((item:any)=>item!==name);console.log(this.caches,'this.caches')},clear(){this.caches=[]}}});03、如果不能使用pnpm,可以先通过npm安装一下
import{defineStore}from"pinia";exportconstuseKeepAliverStore=defineStore("useKeepAliverStore",{state:()=>({caches:[]asany,scrollList:newMap(),//缓存页面组件如果又滚动条的高度}),actions:{add(name:string){this.caches.push(name);},remove(name:string){console.log(this.caches,'this.caches')this.caches=this.caches.filter((item:any)=>item!==name);console.log(this.caches,'this.caches')},clear(){this.caches=[]}}});14、安装完成以后,找到根目录package.json文件中的scripts
参考https://juejin.cn/post/6991653445161713671
import{defineStore}from"pinia";exportconstuseKeepAliverStore=defineStore("useKeepAliverStore",{state:()=>({caches:[]asany,scrollList:newMap(),//缓存页面组件如果又滚动条的高度}),actions:{add(name:string){this.caches.push(name);},remove(name:string){console.log(this.caches,'this.caches')this.caches=this.caches.filter((item:any)=>item!==name);console.log(this.caches,'this.caches')},clear(){this.caches=[]}}});25、执行pnpmrundev则会buildvue源码
import{defineStore}from"pinia";exportconstuseKeepAliverStore=defineStore("useKeepAliverStore",{state:()=>({caches:[]asany,scrollList:newMap(),//缓存页面组件如果又滚动条的高度}),actions:{add(name:string){this.caches.push(name);},remove(name:string){console.log(this.caches,'this.caches')this.caches=this.caches.filter((item:any)=>item!==name);console.log(this.caches,'this.caches')},clear(){this.caches=[]}}});36、然后在....\core\packages\vue\examples\composition中添加一个aehyok.html文件,将如下代码进行拷贝,然后通过chrome浏览器打开,F12,找到源代码的Tab页面,通过快捷键Ctrl+P输入KeepAlive便可以找到这个组件,然后通过左侧行标右键就可以添加断点,进行调试,也可以通过右侧的【调用堆栈】进行快速跳转代码进行调试。
import{defineStore}from"pinia";exportconstuseKeepAliverStore=defineStore("useKeepAliverStore",{state:()=>({caches:[]asany,scrollList:newMap(),//缓存页面组件如果又滚动条的高度}),actions:{add(name:string){this.caches.push(name);},remove(name:string){console.log(this.caches,'this.caches')this.caches=this.caches.filter((item:any)=>item!==name);console.log(this.caches,'this.caches')},clear(){this.caches=[]}}});47、调试源码发现keepalive中的render函数(或者说时setup中的return函数)在子组件切换时就会去执行,变更逻辑缓存
第一次进入页面初始化keepalive组件会执行一次,
然后点击组件一,再次执行render函数
然后点击组件二,会再次执行render函数
8、调试截图说明
9、调试操作,小视频观看
5、vue3keealive源码粗浅分析通过查看vue3KeepAlive.ts源码,源码路径:https://github.com/vuejs/core/blob/main/packages/runtime-core/src/components/KeepAlive.ts
import{defineStore}from"pinia";exportconstuseKeepAliverStore=defineStore("useKeepAliverStore",{state:()=>({caches:[]asany,scrollList:newMap(),//缓存页面组件如果又滚动条的高度}),actions:{add(name:string){this.caches.push(name);},remove(name:string){console.log(this.caches,'this.caches')this.caches=this.caches.filter((item:any)=>item!==name);console.log(this.caches,'this.caches')},clear(){this.caches=[]}}});56、总结通过这次查看vue3keepalive源码发现,其实也没那么难,当然这次查看源代码也只是粗略查看,并没有看的那么细,主要还是先解决问题。动动手调试一下,有时候真的就是不逼一下自己都不知道自己有多么的优秀。原来我也能稍微看看源代码了。以后有空可以多看看vue3源代码,学习一下vue3的精髓。了解vue3更为细节的一些知识点。
原文:https://juejin.cn/post/7103405860449157134