简单手写实现类组件的Ref

972 阅读1分钟

继续学习写源码系列,本系列是学习系列。

  1. 简单手写实现 React 的 createElement 和 render,里面有准备工作,不再赘述。
  2. 简单手写实现 react 的函数组件
  3. 简单手写实现 react 的类组件
  4. 简单手写实现 React 类组件的 state 更新
  5. 简单手写实现 React 类组件的 state 批量更新
  6. 简单手写实现元素的 Ref

本文的目标是,手写实现类组件的Ref

TL;DR

  • createRef 仍然简单的返回{current:null}
  • 类组件身上的ref,指向的就是{current:null},解析属性的时候,其current赋值为类组件的实例

准备工作

先将index.js的点击事件略微修改

// import React from './source/react';
// import ReactDOM from './source/react-dom';
import React from 'react';
import ReactDOM from 'react-dom';
class Form extends React.Component {
  constructor(props) {
    super(props);
    this.textInputRef = React.createRef();
  }
  getFocus = () => {
    // this.textInputRef.current指的是TextInput类的实例,实例有getFocus方法
    this.textInputRef.current.getFocus();
  };
  render() {
    return (
      <>
        <TextInput ref={this.textInputRef} />
        <button onClick={this.getFocus}>获得焦点</button>
      </>
    );
  }
}
class TextInput extends React.Component {
  constructor(props) {
    super(props);
    this.input = React.createRef();
  }
  getFocus = () => {
    this.input.current.focus();
  };
  render() {
    return <input ref={this.input} />;
  }
}
ReactDOM.render(<Form />, document.getElementById('root'));

点击获得焦点,输入框获得焦点:

react_9

分析 ref

  1. <TextInput ref={this.textInputRef} />其实本质就是将this.textInputRef赋值为TextInput类的实例
  2. React.createRef()的返回值始终一致就是{current:null}(元素的时候说过)

实现

1.解析 ref 属性的时候,赋值当前类组件实例

这个也简单,props 属性解析的时候,赋值就好

// react-dom.js
const handleClassType = (vdom) => {
  const { type: classFn, props } = vdom;
  const instance = new classFn(props);
  // props.ref在的话,将实例赋值到ref上 {props:{ref:{current:null}}
  props.ref && (props.ref.current = instance);
  // ...
};

老规矩,index.js打开自己文件的路径

正常运行,✌️~~~