了解如何使用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…