手写React-ref属性

70 阅读1分钟

背景

React中ref属性有两种使用场景:

  • 绑定在普通元素上,用来获取元素DOM(比如下例中在点击事件内可以拿到input的dom,从而完成获取input值的操作,能够完成这种操作的基础就是ref)
  • 绑定在组件上,用来获取组件实例
export default class DemoRef extends Component {
  handle() {
    let value = this.input.value;
    console.log(value);
  }
  render() {
    return (
      <div>
        <input type='text' ref={(input) => (this.input = input)} />
        <button onClick={this.handle.bind(this)}>按钮</button>
        <Alert ref={alert => (this.alert = alert)} />
      </div>
    );
  }
}

思路

对于普通元素,在创建真实DOM元素后,若对应的virtual dom对象的props中存在ref函数,可以将生成的通过回调的方式传递出去。 对于组件,在创建类组件的render virtual dom时,可以获取到component实例,使用virtual dom的props.ref回调可以传递出去。

代码实现

createDOMElement中,创建完真实元素 newElement 后,可以将元素作为参数,通过ref回调传递出去

export default function createDOMElement(vdom) {
  // 创建真实元素 newElement...

  if (vdom.props?.ref) {
    vdom.props?.ref(newElement);
  }

}

mountComponent 中,类组件的render的virtual dom中存储了component实例,可以传递出去

export default function mountComponent (vdom, container, oldDOM) {

	// 获取类组件render virtual dom...

  if (renderedVDOM?.component && vdom.props?.ref) {
    vdom.props?.ref(renderedVDOM?.component);
  }
	// 组件触发生命周期
  renderedVDOM?.component?.componentDidMount();
}