?
Ce document utilise Manuel du site Web PHP chinois Libérer
門戶網站提供了一種一流的方法來將孩子呈現到父組件的 DOM 層次結構之外的 DOM 節(jié)點中。
ReactDOM.createPortal(child, container)
第一個參數(child
)是任何可渲染的 React 子元素,例如元素,字符串或片段。第二個參數(container
)是一個 DOM 元素。
通常,當您從組件的 render 方法中返回一個元素時,它會作為最近的父節(jié)點的子元素裝載到 DOM中:
render() { // React mounts a new div and renders the children into it return ( <div> {this.props.children} </div> );}
但是,有時將子項插入 DOM 中的其他位置很有用:
render() { // React does *not* create a new div. It renders the children into `domNode`. // `domNode` is any valid DOM node, regardless of its location in the DOM. return ReactDOM.createPortal( this.props.children, domNode, );}
門戶的一個典型用例是當父組件具有overflow: hidden
或z-index
樣式時,但您需要孩子直觀地“分離”其容器。例如,對話框,懸浮卡片和工具提示。
注意:重要的是要記住,在使用門戶時,您需要確保遵循適當的可訪問性準則。
在 CodePen 上試用它。
即使門戶網站可以位于 DOM 樹中的任何位置,但其行為與其他方式中的普通 React 子網站相似。像上下文這樣的功能完全一樣,無論孩子是否是門戶網站,因為無論 DOM 樹中的位置如何,門戶網站仍然存在于 React 樹中。
這包括事件冒泡。從門戶內部觸發(fā)的事件將傳播到包含 React 樹中的祖先,即使這些元素不是 DOM 樹中的祖先。假設以下 HTML 結構:
<html> <body> <div id="app-root"></div> <div id="modal-root"></div> </body></html>
一個Parent
組件#app-root
將能夠從兄弟節(jié)點捕獲未捕獲的冒泡事件#modal-root
。
// These two containers are siblings in the DOM const appRoot = document.getElementById('app-root'); const modalRoot = document.getElementById('modal-root'); class Modal extends React.Component { constructor(props) { super(props); this.el = document.createElement('div'); } componentDidMount() { modalRoot.appendChild(this.el); } componentWillUnmount() { modalRoot.removeChild(this.el); } render() { return ReactDOM.createPortal( this.props.children, this.el, ); }} class Parent extends React.Component { constructor(props) { super(props); this.state = {clicks: 0}; this.handleClick = this.handleClick.bind(this); } handleClick() { // This will fire when the button in Child is clicked, // updating Parent's state, even though button // is not direct descendant in the DOM. this.setState(prevState => ({ clicks: prevState.clicks + 1 })); } render() { return ( <div onClick={this.handleClick}> <p>Number of clicks: {this.state.clicks}</p> <p> Open up the browser DevTools to observe that the button is not a child of the div with the onClick handler. </p> <Modal> <Child /> </Modal> </div> ); }}function Child() { // The click event on this button will bubble up to parent, // because there is no 'onClick' attribute defined return ( <div className="modal"> <button>Click</button> </div> ); } ReactDOM.render(<Parent />, appRoot);
在 CodePen 上試用它。
捕獲從父組件中的門戶冒泡的事件允許開發(fā)更加靈活的抽象,這些抽象不是固有地依賴于門戶。例如,如果您渲染<Modal />
組件,則父級可以捕獲其事件,而不管它是否使用門戶實施。