React createRef:引用

一 代码

import React, { Component } from 'react';

class Box extends Component {
    render() {
        return <button>你好</button>;
    }
}

export default class MyComponent extends React.Component {
    constructor(props) {
        super(props);
        this.inputRef = React.createRef(); // 将引用对象设置为父组件的成员
        this.boxRef = React.createRef(); // 将引用对象设置为父组件的成员
    }

     render() {
        return <div>
            {/* ref属性设置在DOM组件上,current指向html元素 */}
            <input type="text" ref={this.inputRef} />
            {/* ref属性设置在普通组件上,current指向普通组件 */}
            <Box ref={this.boxRef}/>
        </div>
     }

    componentDidMount() {
        console.log(this.inputRef); // {current: input}
        console.log(this.inputRef.current); // <input type="text">
        console.log(this.inputRef.current instanceof HTMLInputElement); // true
        this.inputRef.current.focus(); // 操作子组件
        console.log(this.boxRef); // {current: Box}
        console.log(this.boxRef.current); // Box
        console.log(this.boxRef.current instanceof React.Component); // true
    }
}

  

二 原理

 

React.createRef函数会创建一个引用对象(只有一个current属性)。

// react安装包中的react.development.js
// an immutable object with a single mutable(易变的) value
function createRef() {
  var refObject = {
    current: null
  };
  {
    Object.seal(refObject); // 将对象密封(不能增删属性、配置属性,但可以给属性赋值)
  }
  return refObject;
}

子组件创建完成后,会检测其html标签中的ref属性,并做相应的处理。

html标签中的key属性、ref属性,会被React特殊处理,不会出现在props属性中!

// react-dom安装包中的react-dom.development.js

function commitAttachRef(finishedWork) {
  var ref = finishedWork.ref;
  if (ref !== null) {
    var instance = finishedWork.stateNode;
    var instanceToUse = void 0;
    switch (finishedWork.tag) {
      case HostComponent: // 原生html标签
          // 原样返回:function getPublicInstance(instance) {return instance;}
        instanceToUse = getPublicInstance(instance);
        break;
      default:
        instanceToUse = instance; // React组件
    }
    if (typeof ref === 'function') { // ref是函数
      ref(instanceToUse); // 执行
    } else { // ref是引用对象
      {
        if (!ref.hasOwnProperty('current')) {
          warningWithoutStack$1(
        false, 
        'Unexpected ref object provided for %s. ' 
          + 'Use either a ref-setter function or React.createRef().%s', 
        getComponentName(finishedWork.type), getStackByFiberInDevAndProd(finishedWork));
        }
      }

      ref.current = instanceToUse; // 设置引用对象的current属性
    }
  }
}

引用对象是父组件的成员,于是父组件可以通过引用对象操作子组件。

原文地址:https://www.cnblogs.com/sea-breeze/p/10457312.html