react ref 的使用和 react传送门 Portal 作用以及使用

/*
 * @Description: ref 的场景和 传送门 Portal 作用以及使用
 * @Version: 2.0
 * @Autor: lhl
 * @Date: 2020-06-01 10:20:33
 * @LastEditors: lhl
 * @LastEditTime: 2020-06-02 14:07:17
*/ 
import React, { Component, useRef } from 'react'
import ReactDOM from 'react-dom'


export default class App extends Component {
  render() {
    return (
      <div>
        <p>hello react</p>
        <FunRef abc="111"></FunRef>
        <RefClassComponent></RefClassComponent>
        <CbRef></CbRef>
        <Dialog></Dialog>
      </div>
    )
  }
}

// 默认情况下,你不能在函数组件上使用 ref 属性,因为它们没有实例
// 但是特别的,你可以在函数组件内部使用 ref 属性,只要它指向一个 DOM 元素或 class 组件
// 如果要在函数组件中使用 ref,你可以使用 forwardRef 或者可以将该组件转化为 class 组件
function FunRef(props) {
  console.log(props) // {abc: "111"}
  // 这里必须声明 textInput,这样 ref 才可以引用它
  const textInput = useRef(null);
  function handleClick() {
    textInput.current.focus();
  }
  return (
    <div>
      <input
        type="text"
        ref={textInput} />
      <input
        type="button"
        value="聚焦"
        onClick={handleClick}
      />
    </div>
  );
}

// class 组件中ref的使用  如果你目前还在使用 this.refs.xx 这种方式访问 refs ,现在建议用回调函数或 createRef API 的方式代替
class RefClassComponent extends Component {
  constructor(props) {
    super(props);
    this.myRef = React.createRef();
  }
  render() {
    return <div ref={this.myRef} />;
  }
}

// 回调函数的方式 访问 refs React.forwardRef 接受一个渲染函数,其接收 props 和 ref 参数并返回一个 React 节点
class CbRef extends Component {
  render() {
    return (
      <FunRef
        inputRef={el => this.inputElement = el}
      />
    );
  }
}

// createPortal 传送门的使用 Portal 提供了一种将子节点渲染到存在于父组件以外的 DOM 节点的优秀的方案
class Dialog extends React.Component {
  constructor(props) {
      super(props);
      this.el = document.createElement('div');
      this.el.setAttribute('class', 'dailog-box');
  }
  componentDidMount() {
      document.body.appendChild(this.el);
  }
  componentWillUnmount() {
      document.body.removeChild(this.el);
  }
  render() {
      return ReactDOM.createPortal((
          <div className="dailog-content">
              弹窗内容
          </div>
      ), this.el);
  }
}
原文地址:https://www.cnblogs.com/lhl66/p/13030884.html