react系列(19)渲染至父组件以外的节点

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zeping891103/article/details/83998254

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;

该demo实现了PortalsDemo里的子dom节点挂载到了id为"modal-eoot"的dom节点。

猜你喜欢

转载自blog.csdn.net/zeping891103/article/details/83998254
今日推荐