1. 程式人生 > >react系列(19)Portals將子節點渲染到父元件以外的 DOM 節點

react系列(19)Portals將子節點渲染到父元件以外的 DOM 節點

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;