useRef 源码解读

useRef 源码解读

由于 string 类型的 ref 已不推荐使用,所以只针对 function |{current:any} 类型的 ref

与之前 useState 和 useEffect 一样,在 mount 阶段时,会调用 mountRef;在 update 阶段时,会调用 updateRef
在这里插入图片描述
在这里插入图片描述

mountRef

  1. 获取当前 hook 对象
  2. 将 hook.memoizedState 赋值为 ref

其实useRef 最终返回了就是一个普通对象,包含有 current 属性 , {current: initialValue}
在这里插入图片描述

updateRef

很简单

  1. 获取当前 hook 对象
  2. 返回 hook.memoizedState ,即 返回 ref 对象

在这里插入图片描述

若是类组件实现 ref ,使用的是 createRef 函数来创建的对象,而且也是一样的 有 current 属性的对象
在这里插入图片描述

ref 的生命周期(工作流程)

一般我们在 HostComponent,ClassComponent,FunctionComponent ,ForwardRef 里面都可以使用 ref 属性,ref 属性的值一般是 一个函数或者是 一个包含current 属性的对象

比如:

<Home ref={homeRef} />
<div ref={divRef} />

对于一个 函数类型的 ref 来说,在 ref的不同生命周期中,这个 function ref 都会被调用,并且它的传参是不一样的;

对于一个包含 current 属性的对象来说,在 ref的不同生命周期中,current 属性对应的值也是不一样的

总结:

ref 的工作流程可以分为两部分:

  • render 阶段为含有 ref 属性的 fiber 添加 Ref effectTag
  • commit 阶段为包含 Ref effectTag 的 fiber 执行对应的操作
render 阶段

主要是 markRef 函数

在首屏渲染时,并且有ref 属性的情况下,

或者 在 update 时,并且 ref 改变的情况下,都会为当前 fiber 加上 Ref 的 effectTag
在这里插入图片描述

commit 阶段
总述

当标记完之后,进入 commit 阶段。

  1. 对于 ref 属性改变的情况,需要先移除之前的 ref

  2. 对于 Deletion effectTag 的 fiber(对应需要删除的DOM 节点),需要递归它的子树,对 子孙 fiber 的 ref 执行类似 commitDetachRef 的操作,这一步主要是 safelyDetachRef 函数

  3. 进入 ref 的赋值阶段,commitLayoutEffect 会执行 commitAttachRef (赋值 ref)

具体阐述

当标记完之后,进入 commit 阶段。

  1. 对于 ref 属性改变的情况,需要先移除之前的 ref

  2. 对于 Deletion effectTag 的 fiber(对应需要删除的DOM 节点),需要递归它的子树,对 子孙 fiber 的 ref 执行类似 commitDetachRef 的操作,这一步主要是 safelyDetachRef 函数

safelyDetachRef

递归子树,对子树中每个 fiber 节点执行 commitunmount
在这里插入图片描述

在 commitunmount 中,会根据fiber 的类型来做不同的处理
在这里插入图片描述
比如说若是 classComponent 类型的话,不仅会执行 safelyDetachRef ,还会判断 实例中是否存在 componentWillUnmount 的生命周期函数,若存在,还会执行 这个生命周期函数:
在这里插入图片描述

在 safelyDetachRef 函数中,若是 函数类型的 ref,会执行 ref 函数,参数为null;

若是对象类型的,就是把 current 属性赋值为 null:
在这里插入图片描述

  1. 进入 ref 的赋值阶段,commitLayoutEffect 会执行 commitAttachRef (赋值 ref)
commitAttachRef
  1. 通过当前fiber的 tag 来获取对应的实例,对于 HostComponent ,实例就是获取到的 DOM 节点,其他情况就是 fiber.stateNode
  2. 判断 ref 的类型,如果是 函数类型,调用 ref 函数并将实例传过去;若不是,则将 ref.current 赋值为该 实例

在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值