wangzhenggui/blog

react读源码系列之初步了解ref

Opened this issue · 0 comments

前言

在react典型的数据流中,props传递是父子组件交互的唯一方式;在react典型的数据量之外,某些情况下(例如和第三方的dom库整合,或者某个dom元素focus等)为了修改子组件我们可能需要另一种方式,这就是ref方式。

初步认识ref

在react代码中我们可以通过3种方式来创建ref;
1、string ref
2、function
3、createRef(官方推荐)

通过代码来看下上面3种实现方式

首先看下string ref的方式创建

<div ref="div" />  // 这里我们直接定义一个string类型的ref属性

然后在使用的时候,可以直接通过this.refs.div的方式来获取实例,其实就是dom元素节点。

在看下function的方式是如何创建的

<div ref={instance => this.divRef = instance}></div>  // 这里我们的ref是一个函数的形式

然后使用的时候,可以直接通过this.divRef的方式来获取实例,这个地方的实例也是dom节点,当然ref也是可以作用于组件上面的,只不过这里举例用的是dom节点而已

最后看下官方推介的使用方式

constructor() {
    super()
    this.objRef = React.createRef()
    // {current: null} 初始化的objRef的数据结构
  }

<div ref={this.objRef}></div>    // 这里将ref绑定到this.objRef上

这里我们要得到实例,可以通过this.objRef.current获取到,然后对实例节点进行操作。

添加项

1、高阶组件中如何获取到低阶组件中的ref

高阶组件在props中定义一个钩子函数
setRefs = (instance) => {
    this.productsRef = instance
  }
<WrappedComponent
      getRefs={instance => this.setRefs(instance)}
/>

低阶组件中定一个函数,当组件挂载的时候就会执行这个方法,然后回将当前节点对象作为参数传递到定的函数中,在去执行高阶组件的钩子函数,从而使高阶组件能够得到低阶组件中的ref

refcb = (instance) => {
    this.props.getRefs(instance)
  }
<div ref={this.refcb}></div>

2、函数式组件如何能够使用ref

这里我们通过使用React.forwardRef就可以能够得到组件的ref属性
const TargetComponent = React.forwardRef((props, ref) => {
  return <div ref={ref}></div>
})  // 无状态组件,这里其实是通过函数的方式定义的组件

constructor() {
    super()
    this.targetRef = React.createRef() // 定义 ref
    // {current: null}
  }
<TargetComponent ref={this.targetRef}/> 

其实这个地方也可以解决上面高阶组件获取ref的问题,只要在低阶组件中使用 React.forwardRef进行节点绑定就可以了。