如何使用React Portals

228 阅读1分钟

了解如何使用React Portals

门户是一种在其组件层次结构之外,在一个单独的组件中渲染一个元素的方式。

当该事件被渲染时,发生在它身上的事件由React组件层次结构管理,而不是由元素的DOM位置设置的层次结构。

因此被称为 "门户":一个元素位于DOM树的某处,在正常的React组件树之外,但包括它的React组件树仍然负责。

React提供了一个简单的API来做到这一点,ReactDOM.createPortal() ,它接受两个参数。第一个是要渲染的元素,第二个是渲染它的DOM元素。

这方面的一个经典用例是模态窗口。

一个全屏呈现的模态必须在元素之外,所以它可以使用CSS进行适当的样式设计。

因此,如果一个模态被定义为一个组件。

class Modal extends React.Component {
  constructor(props) {
    super(props)
    this.el = document.createElement('div')
  }

  componentDidMount() {
    document.getElementById('modal').appendChild(this.el)
  }

  componentWillUnmount() {
    document.getElementById('modal').removeChild(this.el)
  }

  render() {
    return ReactDOM.createPortal(
      this.props.children,
      this.el
    )
  }
}

我们可以让一个App组件来渲染它,所有发生在模态组件中的事件都将由App来处理,尽管技术上模态是在一个不同的DOM树中渲染的。

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

    this.handleShow = this.handleShow.bind(this)
    this.handleHide = this.handleHide.bind(this)
  }

  handleShow() {
    this.setState({showModal: true})
  }

  handleHide() {
    this.setState({showModal: false})
  }

  render() {
    const modal = this.state.showModal ? (
      <Modal>
        <div>
          The modal <button onClick={this.handleHide}>Hide</button>
        </div>
      </Modal>
    ) : ''

    return (
      <div>
        The app <button onClick={this.handleShow}>Show modal</button>
        {modal}
      </div>
    )
  }
}

ReactDOM.render(<App />, document.getElementById('app'))

请看完整的例子,codepen.io/flaviocopes…