总结ref的用法

本文详细介绍了React中ref的使用方式,包括string类型的ref、function类型的ref以及通过React.createRef()和useRef创建的ref。同时,深入探讨了ref在React生命周期中的工作原理,包括render阶段和commit阶段的操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

ref通常被用来获取DOM元素或组件实例

string类型的ref

<input type='text' ref='input' />
......
console.log(this.$refs.input)   //  <input type='text' />

$refs 是所有注册过的ref的一个集合

在react中,一般使用function类型的ref,上面的这种string类型的ref将会被废弃,因为它无法直接获取this的指向,并且当使用render回调函数的开发模式,获得ref的组件实例可能与预期不同。

function类型的ref

<WebView ref={ref => this.webview =  ref } // 将该组件赋值给webview />
console.log(this.webview)

通过React.createRef()创建ref:

this.webview = React.createRef();
// 引用
<WebView ref={this.webview} />
// 获取当前节点
console.warn(this.webview.current)

React.createRef()创建的ref对象仅仅包含current属性,表示获取的DOM元素或组件实例

useRef

useRef 返回一个可变的 ref 对象,其 .current 属性被初始化为传入的参数(initialValue)。返回的 ref 对象在组件的整个生命周期内保持不变。

即每次返回的ref对象都是一开始传入的

const refContainer = useRef(initialValue);

ref的生命周期

在React中,HostComponent、ClassComponent、ForwardRef可以赋值ref属性。ForwardRef只是将ref作为第二个参数传递下去,没有别的特殊处理。

Ref属性在ref不同的生命周期会被执行 ( fuction类型 ) 或赋值 ( {current: any}对象类型 )

ref的生命周期与react的渲染一样,可以分为 两个阶段

render阶段:

为含有ref属性的Component对应fiber添加Ref effectTag,fiber类型为HostComponent、ClassComponent、ScopeComponent

  • 对于mount,workInProgress.ref !== null,即组件首次render时存在ref属性
  • 对于update,current.ref !== workInProgress.ref,即组件更新时ref属性改变
commit阶段:

为包含Ref effectTag的fiber执行对应操作

  • 移除之前的ref
function commitDetachRef(current: Fiber) {
  const currentRef = current.ref;
  if (currentRef !== null) {
    if (typeof currentRef === 'function') {
      // function类型ref,调用他,传参为null
      currentRef(null);
    } else {
      // 对象类型ref,current赋值为null
      currentRef.current = null;
    }
  }
}
  • 更新ref
function commitAttachRef(finishedWork: Fiber) {
  // finishedWork为含有Ref effectTag的fiber
  const ref = finishedWork.ref;
  
  // 含有ref prop,这里是作为数据结构
  if (ref !== null) {
    // 获取ref属性对应的Component实例
    const instance = finishedWork.stateNode;
    let instanceToUse;
    switch (finishedWork.tag) {
      case HostComponent:
        // 对于HostComponent,实例为对应DOM节点
        instanceToUse = getPublicInstance(instance);
        break;
      default:
        // 其他类型实例为fiber.stateNode
        instanceToUse = instance;
    }

    // 赋值ref
    if (typeof ref === 'function') {
      ref(instanceToUse);
    } else {
      ref.current = instanceToUse;
    }
  }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值