位置: IT常识 - 正文

【手撕源码】vue2.x中keep-alive源码解析(手撕视频教程全集)

编辑:rootadmin
【手撕源码】vue2.x中keep-alive源码解析

推荐整理分享【手撕源码】vue2.x中keep-alive源码解析(手撕视频教程全集),希望有所帮助,仅作参考,欢迎阅读内容。

文章相关热门搜索词:手撕代码题目集锦,手撕代码是指在纸上写吗,手撕算法是什么意思,什么叫手撕代码,什么叫手撕代码,手撕代码题目集锦,手撕代码题目集锦,什么叫手撕代码,内容如对您有帮助,希望把文章链接给更多的朋友!

🐱 个人主页:不叫猫先生 🙋‍♂️ 作者简介:前端领域新星创作者、阿里云专家博主,专注于前端各领域技术,共同学习共同进步,一起加油呀! 💫系列专栏:vue3从入门到精通、TypeScript从入门到实践 📢 资料领取:前端进阶资料以及文中源码可以找我免费领取 🔥 前端学习交流:博主建立了一个前端交流群,汇集了各路大神,一起交流学习,期待你的加入!(文末有我wx或者私信)

目录一、前世尘缘二、keep-alive内置组件1.缓存动态组件2.缓存路由组件3.原理解析(1)keep-alive 在生命周期中做了什么?(2)源码(3)abstract:true(4)pruneCacheEntry函数(5)render三、LRU算法一、前世尘缘

vue中内置组件keep-alive的设计思想源于HTTP中的Keep-Alive模式,Keep-Alive模式避免频繁创建、销毁链接,允许多个请求和响应使用同一个HTTP链接。 HTTP 1.0 中keep-alive默认是关闭的,需要在HTTP头加入"Connection: Keep-Alive",才能启用Keep-Alive;HTTP 1.1中默认启用Keep-Alive,如果加入"Connection: close ",才关闭。目前大部分浏览器都是用HTTP 1.1协议。

二、keep-alive内置组件

作用:动态切换组件时缓存组件实例,避免dom重新渲染。

1.缓存动态组件

当组件为componentOne时缓存该组件实例

<keep-alive :include="componentOne`" :exclude="componentTwo" :max="num"> <component :is="currentComponent"></component> </keep-alive>2.缓存路由组件【手撕源码】vue2.x中keep-alive源码解析(手撕视频教程全集)

注意缓存路由组件vue2.x与vue3.x有区别,vue2.x用法如下:

<keep-alive :include="componentOne`" :exclude="componentTwo" :max="num"> <router-view :is="currentComponent"></router-view> </keep-alive>

vue3.x用法如下:

<router-view v-slot="{ Component }"> <keep-alive :include="includeList"> <component :is="Component"/> </keep-alive></router-view>3.原理解析

缓存的组件以 [key,vnode] 的形式记录,keys记录缓存的组件key,依据inclued、exclude的值,并且当超过设置的max根据LUR算法进行清除。vue2.x和vue3.x相差不大。

(1)keep-alive 在生命周期中做了什么?created:初始化catch,keys。catch是一个缓存组件虚拟dom的数组,其中数组中对象的key是组件的key,value是组件的虚拟dom;keys是一个用来缓存组件的key的数组。mounted:实时监听include、exclude属性的变化,并执行相应操作。destroyed:删除掉所有缓存相关的数据。(2)源码

地址:源码地址

// 源码位置:src/core/components/keep-alive.jsexport default { name: 'keep-alive', abstract: true, props: { include: patternTypes, exclude: patternTypes, max: [String, Number] }, created () { this.cache = Object.create(null) this.keys = [] }, destroyed () { for (const key in this.cache) { pruneCacheEntry(this.cache, key, this.keys) } }, mounted () { //查看是否有缓存没有缓存的话直接走缓存 this.cacheVNode() // 这里借助 watch 监控 include 和 exclude // 如果有变化的话,则按照最新的 include 和 exclude 更新 this.cache // 将不满足 include、exclude 限制的 缓存vnode 从 this.cache 中移除 this.$watch('include', val => { pruneCache(this, name => matches(val, name)) }) this.$watch('exclude', val => { pruneCache(this, name => !matches(val, name)) }) }, updated() { this.cacheVNode() }, methods:{ cacheVNode() { const { cache, keys, vnodeToCache, keyToCache } = this if (vnodeToCache) { const { tag, componentInstance, componentOptions } = vnodeToCache cache[keyToCache] = { name: _getComponentName(componentOptions), tag, componentInstance } keys.push(keyToCache) // prune oldest entry if (this.max && keys.length > parseInt(this.max)) { pruneCacheEntry(cache, keys[0], keys, this._vnode) } this.vnodeToCache = null } } }, render(){ //下面详细介绍 }}(3)abstract:true

设置为true时,表面该组件为抽象组件,抽象组件不会和子组件建立父子关系,组件实例会根据这个属性决定是否忽略该组件,所以并不会有节点渲染在页面中。

(4)pruneCacheEntry函数

destoryed周期中循环了所有缓存的组件,并用 pruneCacheEntry进行处理,pruneCacheEntry做了什么事?

// src/core/components/keep-alive.jsfunction pruneCacheEntry ( cache: VNodeCache, key: string, keys: Array<string>, current?: VNode) { const cached = cache[key] if (cached && (!current || cached.tag !== current.tag)) { cached.componentInstance.$destroy() // 执行组件的destory钩子函数 } cache[key] = null // cache中对象的key设为null remove(keys, key) // 删除keys对应的元素}

destoryed周期中,删除缓存组件的所有数组,pruneCacheEntry主要做了这几件事:

遍历缓存组件集合(cach),对所有缓存的组件执行$destroy方法清除cache中key的值清除keys中的key(5)render

render中主要做了什么?

获取keep-alive组件子节点中第一个组件的vnode、componentOptions、name如果name存在且不在include中或者存在在exclude中,则返回虚拟dom。此时该组件并没有使用缓存。接下来就是上面的else情况:使用keep-alive进行组件缓存,根据组件id,tag生成组件的key,如果cache集合中存在以key为属性名的vdom,,说明组件已经缓存过,则将缓存的 Vue 实例赋值给 vnode.componentInstance,从keys中删除key,再把key push导keys中,保证当前key在keys的最后面(这是LRU算法的关键)。如果不存在则继续走下面如果cach[key]不存在则为第一次加载组件,则把vdom赋值给cach[key],key push到key如果keys的长度大于max,则进行组件缓存清理,则把不经常使用的被缓存下来的在keys中排第一位的组件清除掉,清除也是调用的pruneCacheEntry方法render () {// 获取 keep-alive 组件子节点中的第一个组件 vnode const slot = this.$slots.default const vnode = getFirstComponentChild(slot) // 获取组件的配置选项对象 const componentOptions = vnode && vnode.componentOptions if (componentOptions) { // 获取组件的名称 const name = _getComponentName(componentOptions) const { include, exclude } = this // 如果当前的组件 name 不在 include 中或者组件的 name 在 exclude 中 // 说明当前的组件是不被 keep-alive 所缓存的,此时直接 return vnode 即可 if ( // not included (include && (!name || !matches(include, name))) || // excluded (exclude && name && matches(exclude, name)) ) { return vnode } // 代码执行到这里,说明当前的组件受 keep-alive 组件的缓存 const { cache, keys } = this // 定义 vnode 缓存用的 key const key = vnode.key == null ? // same constructor may get registered as different local components // so cid alone is not enough (#3269) componentOptions.Ctor.cid + (componentOptions.tag ? `::${componentOptions.tag}` : '') : vnode.key // 如果 cache[key] 已经存在的话,则说明当前的组件 vnode 已经被缓存过了,此时需要将其恢复还原出来 if (cache[key]) { // 将缓存的 Vue 实例赋值给 vnode.componentInstance vnode.componentInstance = cache[key].componentInstance // make current key freshest // 先从 keys 中移除 key,然后再 push key,这可以保证当前的 key 在 keys 数组中的最后面 remove(keys, key) keys.push(key) } else { // delay setting the cache until update // 如果 cache[key] 不存在的话,说明当前的子组件是第一次出现,此时需要将 vnode 缓存到 cache 中,将 key 存储到 keys 字符串数组中。这里是用一个中间变量接收,当数据变化时触发updated去调用cacheVNode方法。 this.vnodeToCache = vnode this.keyToCache = key } // @ts-expect-error can vnode.data can be undefined // 将 vnode.data.keepAlive 属性设置为 true,这对 vnode 有一个标识的作用,标识这个 // vnode 是 keep-alive 组件的 render 函数 return 出去的,这个标识在下面的运行代码中有用 vnode.data.keepAlive = true } return vnode || (slot && slot[0]) }三、LRU算法

缓存的组件在进行清除的时候使用了LRU算法,具体是什么策略呢?当数据超过了限定空间的时候对数据清理,清理的原则是对很久没有使用到过的数据进行清除。

本文链接地址:https://www.jiuchutong.com/zhishi/300683.html 转载请保留说明!

上一篇:国内版的ChatGPT弯道超车的机会在哪里?(国内版的chatpdf)

下一篇:【创作赢红包】项目信息分析表

  • iphone13pro怎么无线充电(iphone13pro无线)

    iphone13pro怎么无线充电(iphone13pro无线)

  • 手机上健康码怎么弄(手机上健康码怎么找)

    手机上健康码怎么弄(手机上健康码怎么找)

  • 荣耀30pro微信怎么开美颜视频(荣耀30pro微信怎么加密)

    荣耀30pro微信怎么开美颜视频(荣耀30pro微信怎么加密)

  • 戴尔win10睡眠无法唤醒(戴尔电脑进入休眠唤醒不了)

    戴尔win10睡眠无法唤醒(戴尔电脑进入休眠唤醒不了)

  • 苹果手机陌生人打不进来怎么回事(苹果手机陌生人打进来一直在通话中怎么办)

    苹果手机陌生人打不进来怎么回事(苹果手机陌生人打进来一直在通话中怎么办)

  • 华为手机智慧语音是什么(华为手机智慧语音叫什么名字)

    华为手机智慧语音是什么(华为手机智慧语音叫什么名字)

  • 苹果11充电口检测有水咋办(苹果11充电口检测到液体)

    苹果11充电口检测有水咋办(苹果11充电口检测到液体)

  • b550主板什么时候出(b550主板上市)

    b550主板什么时候出(b550主板上市)

  • 什么是h5技术(h5 技术)

    什么是h5技术(h5 技术)

  • 为什么cad打印的时候有些不显示(为什么cad打印的线是波浪线)

    为什么cad打印的时候有些不显示(为什么cad打印的线是波浪线)

  • 腾讯视频怎么取消会员(腾讯视频怎么取消连续包月自动续费)

    腾讯视频怎么取消会员(腾讯视频怎么取消连续包月自动续费)

  • 户户通频道少了怎么办(户户通频道少了有什么办法)

    户户通频道少了怎么办(户户通频道少了有什么办法)

  • 手机微信来电不反应(手机微信来电不响铃怎么回事)

    手机微信来电不反应(手机微信来电不响铃怎么回事)

  • v1932a是什么手机(v1938a是什么型号手机)

    v1932a是什么手机(v1938a是什么型号手机)

  • ipad ios9.0什么意思(ipad9.0版本)

    ipad ios9.0什么意思(ipad9.0版本)

  • 号码拉黑了打电话有提示吗(号码拉黑了打电话过去还有信息不)

    号码拉黑了打电话有提示吗(号码拉黑了打电话过去还有信息不)

  • PS中如何把图片变亮(ps中如何把图片放大)

    PS中如何把图片变亮(ps中如何把图片放大)

  • 发热袋怎么使用(发热袋怎么使用视频)

    发热袋怎么使用(发热袋怎么使用视频)

  • 腾讯地图如何设置免流(腾讯地图如何设置货车导航)

    腾讯地图如何设置免流(腾讯地图如何设置货车导航)

  • 抖音视频如何剪辑拼接(抖音视频如何剪切)

    抖音视频如何剪辑拼接(抖音视频如何剪切)

  • 苹果11是双卡的吗(苹果11是双卡的吗?怎么装双卡)

    苹果11是双卡的吗(苹果11是双卡的吗?怎么装双卡)

  • 看朋友圈怎么选择时间(看朋友圈怎么选日期查看)

    看朋友圈怎么选择时间(看朋友圈怎么选日期查看)

  • 快手超级管理员和管理员的区别(快手超级管理员有几个)

    快手超级管理员和管理员的区别(快手超级管理员有几个)

  • 快手私信如何自动回复(快手私信怎么自动发消息?)

    快手私信如何自动回复(快手私信怎么自动发消息?)

  • 华为p30pro快充多少w(华为p30pro快充多少变成普通充电)

    华为p30pro快充多少w(华为p30pro快充多少变成普通充电)

  • vivo手机微信卡怎么办(vivo手机微信卡顿怎么解决)

    vivo手机微信卡怎么办(vivo手机微信卡顿怎么解决)

  • 三星s8耳机akg什么型号(三星s8配的akg耳机多少钱)

    三星s8耳机akg什么型号(三星s8配的akg耳机多少钱)

  • 电脑缩小窗口快捷键(电脑缩小窗口快捷键是啥)

    电脑缩小窗口快捷键(电脑缩小窗口快捷键是啥)

  • TS基础了解一(ts基础类型)

    TS基础了解一(ts基础类型)

  • 小规模销售收入免税会计分录
  • 分公司缴税企业所得税
  • 污水处理税收优惠政策
  • 公司资料更新
  • 房产税计税依据
  • 外购商品对外捐赠分录
  • 产品成本核算需要经过哪些程序
  • 固定资产投资转化为gdp比例
  • 固定资产盘亏是营业外支出吗
  • 收到投资款现金流量项目是什么
  • 营改增后房地产公司税种及税率
  • 分期付款方式购物划算吗
  • 增值税专用发票有效期是多长时间
  • 开专用发票的地址有错会有影响吗?
  • 现金流量计划中的税金怎么算
  • 工会经费减除项填什么
  • 出口退税预审在申报系统怎么做
  • 虚开增值税发票不能忽略的三个点!
  • spss安装后无法启动许可证授权向导
  • win11家庭版怎么激活
  • 跨行汇入会计分录
  • php论坛代码
  • 电力安装有前途吗
  • linux系统设置中文语言
  • linux操作系统有哪些版本
  • 经营性租赁与融资性租赁
  • 房地产企业土地使用税计算方法
  • 最小的摄像头是多大
  • php对象缓存
  • if.else
  • 银行借款利息支出计入什么科目
  • 购买办公用品没收到发票怎么做账
  • auto learn
  • 双重差分法(DID)
  • php判断文件类型
  • yolox改进
  • 小程序从入门到精通
  • php教程从入门到精通
  • 增值税专用发票丢了怎么补救
  • mysql一次io
  • python 熵值法
  • 购买方销项负数发票怎么抵扣
  • 建筑业外管证预审要多久
  • 建筑企业小规模纳税人
  • 企业月末在产品数量变化不大时,最适宜
  • 三免三减半税收政策中的递延所得税
  • 哪些人需要税务会计
  • 其他非流动资产是会计科目吗
  • 小微企业全年营业额不能超过多少
  • 稳岗补贴缴纳社保个人部分还是公司部分
  • 拨缴经费收入
  • 公司基本账户提额怎么算
  • 什么是电子银行服务
  • 重分类调整的内容包括什么
  • 城建税教育费附加和地方教育费附加
  • 建筑企业预缴税
  • 被挂靠方并收取管理费的公司怎样处理账务?
  • 呆滞原材料变卖的会计处理
  • 上个月多计提的费用怎么调整
  • 客户给的现金如何转到公司账上
  • 应收帐款收不回来怎么做会计分录
  • 长期股权投资的初始计量
  • windows使用痕迹是指是什么
  • linux实现mysql数据库每天自动备份定时备份
  • 删除sql server2008
  • windowsxp教程
  • windows10玩lol有延迟怎么办
  • 如何修改注册表值
  • centos fuser
  • 基于嵌入式linux的课程设计
  • windows 打开文件命令
  • win8.1如何更新到win10
  • javascript弹窗函数
  • jquery提交表单调用serialize方法
  • unity projector
  • javascriptz
  • css图片渐变效果
  • 房产税纳税义务时间
  • 乌鲁木齐税收政策
  • 哪些账本需要贴纸
  • 免责声明:网站部分图片文字素材来源于网络,如有侵权,请及时告知,我们会第一时间删除,谢谢! 邮箱:opceo@qq.com

    鄂ICP备2023003026号

    网站地图: 企业信息 工商信息 财税知识 网络常识 编程技术

    友情链接: 武汉网站建设