React之ref的实现原理

570 阅读2分钟

前言

  • Refs提供了一种方式,允许我们访问DOM节点或在render方法中创建React元素
  • 可以使用ref去存储DOM节点的引用
  • 当ref属性用于HTML元素时,构造函数中使用Ract.createRef()创建的ref接收底层的DOM元素作为其current属性

示例

image.png

实现

给原生DOM加ref

在react.js中

image.png

在react-dom.js中的createDOM方法中

image.png

  • 从虚拟dom中多结构出一个ref

在createDOM里的根据虚拟DOM生成真实DOM后,判断ref属性是否存在,如果存在,就把真实DOM赋值给ref里的current属性

image.png

上述我们就实现了给原生DOM元素绑定ref

给类组件加ref

父组件

image.png

子组件

image.png

实现给类组件加ref

在react-dom.js中的mountClassComponent方法里

image.png

  • 结构出虚拟DOM上的ref
  • 然后在创建类组件实例后,判断ref是否存在,如果存在,就把实例赋值给ref上的current属性

给函数组件加ref

image.png

我们运行代码。会发现报错

image.png

注意:函数组件不能给ref,我们要想在函数组件用ref,必须用React.forwardRef()

image.png

  • 父组件传的ref,在子组件的第二个参拿到,直接传给DOM

实现React.forwardRef()方法

先增加一个常量

image.png

在react.js中

image.png

回到react-dom.js中,找到createDOM方法

image.png

  •  增加判断如果type有值,并且type的$$typeof值命中forwardref标识
  • 调用montForwardComponent处理,传入虚拟dom

我们先来理解下过程

image.png

  • 函数组件=>babel转译=>浏览器执行
  •  最后得到的是一个对象,我们下面要把这个对象变成虚拟dom,然后再变成真实DOM

montForwardComponent方法

image.png

  • 先结构出type、props和ref
  • 得到老的函数组件虚拟dom,在调用老的函数组件时传入props和ref
  • 最后调用createDOM创建真实DOM,这个方法前面篇章有实现