Portals

React 16 的 Portals 特性让我们可以把组件渲染到当前组件树以外的 DOM 节点上,这个特性典型的应用场景是渲染应用的全局弹框,使用 Portals 后,任意组件都可以将弹框组件渲染到根节点上,以方便弹框的显示。Portals 的实现依赖 ReactDOM 的一个新的 API:

ReactDOMO.createPortal(child, container)

第一个参数 child 是可以被渲染的 React 节点,例如 React 元素、由 React 元素组成的数组、字符串等,container 是一个 DOM 元素,child 将被挂载到这个 DOM 节点。

我们创建一个 Modal 组件,Modal 使用 ReactDOM.createPortal() 在 DOM 根节点上创建一个弹框:

class Modal extends Component {
  constructor(props) {
    super(props);
    // 根节点下创建一个 div 节点
    this.container = document.createElement("div");
    document.body.appendChild(this.container);
  }

  componentWillUnmount() {
    document.body.removeChild(this.container);
  }

  render() {
    // 创建的 DOM 树挂载到 this.container 指向的 div 节点下面
    return ReactDOM.createPortal(
      <div className="modal">
        <span className="close" onClick={this.props.onClose}>
          &times;
        </span>
        <div className="content">{this.props.children}</div>
      </div>,
      this.container
    );
  }
}

在 App 中使用 Modal:

class App extends Component {
  constructor(props) {
    super(props);
    this.state = { showModal: true };
  }

  closeModal = () => {
    this.setState({ showModal: false });
  };

  render() {
    return (
      <div>
        <h2>Dashboard</h2>
        {this.state.showModal && (
          <Modal onClose={this.closeModal}>Modal Dialog </Modal>
        )}
      </div>
    );
  }
}

export default App;

本节项目源代码的目录为 /chapter-03/react16-portals 。