react系列(19)Portals將子節點渲染到父元件以外的 DOM 節點
阿新 • • 發佈:2018-12-21
Portals 提供了一種很好的將子節點渲染到父元件以外的 DOM 節點的方式。API如下:
ReactDOM.createPortal(child, container)
第一個引數(child
)是任何可渲染的React的子元素,例如一個元素,字串或碎片。第二個引數(container
)則是一個 DOM 元素。對於 portal 的一個典型用例是當父元件有 overflow: hidden
或 z-index
樣式,但你需要子元件能夠在視覺上“跳出(break out)”其容器。例如,對話方塊、hovercards以及提示框。
實現模態彈框效果Demo如下:Modal.jsx
import React from 'react'; import ReactDOM from 'react-dom'; class Modal extends React.Component { constructor(props) { super(props); this.state = {}; this.el = document.createElement('div'); } componentDidMount() { document.getElementById('modal-root').appendChild(this.el); } componentWillUnmount() { document.getElementById('modal-root').removeChild(this.el); } render() { return ReactDOM.createPortal( this.props.children, this.el, ); } } export default Modal;
PortalsDemo.jsx
import React from 'react'; import Modal from './Modal.jsx'; // Portals 用法 import './../../css/modal.css'; class PortalsDemo 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 className="modal" onClick={this.handleHide}> <button>Hide modal</button> </div> </Modal> ) : null; return( <div className="app"> <button onClick={this.handleShow}>Show modal</button> {modal} </div> ); } } export default PortalsDemo;
model.css
.modal {
background-color: rgba(0, 0, 0, 0.5);
position: fixed;
height: 100%;
width: 100%;
top: 0;
left: 0;
display: flex;
align-items: center;
justify-content: center;
}
App.jsx
import React from 'react'; import PortalsDemo from './components/portals/PortalsDemo.jsx'; // Portals 用法 class App extends React.Component { constructor(props) { super(props); this.state = {}; } render() { return( <React.Fragment> <div id="app-root"> <PortalsDemo></PortalsDemo> </div> <div id="modal-root"></div> </React.Fragment> ); } } export default App;