Ref 对象创建
①类组件React.createRef
创建了一个对象,对象上的 current 属性,用于保存通过 ref 获取的 DOM 元素,组件实例等。
②函数组件 useRef
用 hooks 中的 useRef 来达到同样的效果
区别:
ref 保存位置不相同。
- 类组件有一个实例 instance 能够维护像 ref 这种信息
- 函数组件每次更新都是一次新的开始,所有变量重新声明,ref 就会随着函数组件执行被重置
解决:hooks 和函数组件对应的 fiber 对象建立起关联,将 useRef 产生的 ref 对象挂到函数组件对应的 fiber 上,函数组件每次执行,只要组件不被销毁,函数组件对应的 fiber 对象一直存在,所以 ref 等信息就会被保存下来。
类组件获取 Ref 三种方式
① Ref属性是一个字符串
React 在底层逻辑,会判断字符串 ref 标记的类型,如果是 DOM 元素,会把真实 DOM 绑定在组件 this.refs (组件实例下的 refs )属性上,如果是类组件,会把子组件的实例绑定在 this.refs 上。
② Ref 属性是一个函数
ref 标记类型是函数的时候,将作为 callback 形式,等到真实 DOM 创建阶段,执行 callback ,获取的 DOM 元素或组件实例,将以回调函数第一个参数形式传入,
③ Ref属性是一个ref对象
Ref 高阶用法
1、forwardRef 转发 Ref
1)跨层级获取:比如想要通过标记子组件 ref ,来获取孙组件的某一 DOM 元素,或者是组件实例。
2)合并转发ref:可以用来传递合并之后的自定义的 ref。forwardRef
让 ref 可以通过 props 传递,那么如果用 ref 对象标记的 ref ,那么 ref 对象就可以通过 props 的形式,提供给子孙组件消费,当然子孙组件也可以改变 ref 对象里面的属性
3)高阶组件转发:
2、ref实现组件通信
父组件可以通过 ref 模式标记子组件实例,从而操纵子组件方法
例如:参考 antd 里面的 form 表单,暴露出对外的 resetFields
, setFieldsValue
等接口,可以通过表单实例调用这些 API 。
① 类组件 ref
可以通过 ref 直接获取组件实例,实现组件通信。
如下:
- 1 子组件暴露方法 fatherSay 供父组件使用,父组件通过调用方法可以设置子组件展示内容。
- 2 父组件提供给子组件 toFather,子组件调用,改变父组件展示内容,实现父 <-> 子 双向通信。
/* 子组件 */
class Son extends React.PureComponent{
state={
fatherMes:'',
sonMes:''
}
fatherSay=(fatherMes)=> this.setState({
fatherMes })