Portal
Portals 提供了一个最好的在父组件包含的DOM结构层级外的DOM节点渲染组件的方法。
应用场景:当在react中想实现一个类似于dialog的全局组件,此时该组件的样式很容易收到父组件、兄弟组件的干扰(z-index,拼爹原则:当兄弟组件都有z-index,一个大于另一个的时候,小的那个组件的子组件的z-index就算在大也没有用,优先级仍然还是低于z-index较大的那个组件)
1 2
| ReactDOM.createPortal(child,container);
|
普通的组件,子组件的元素将挂载到父组件的DOM节点中。
一个典型的用法就是当父组件的dom元素有 overflow:hidden 或者 z-inde 样式,而你又需要显示的子元素超出父元素的盒子。举例来说,如对话框,悬浮框,和小提示。
示例:
App.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| import React, {Component} from 'react'; import './App.css' import PortalDialog from "./components/PortalDialog"; class App extends Component { state = { isShow:false } render() { return ( <div className="box"> <div className="left"></div> <div className="right"> <button onClick={() => { this.setState({ isShow:true }) }}>click</button> { this.state.isShow && <PortalDialog onClose={() => { this.setState({ isShow:false }) } }></PortalDialog> } </div> </div> ); } }
export default App;
|
App.css
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| *{ margin: 0; padding: 0; } .left,.right { height: 100vh; } .box { display: flex; }
.left { width: 200px; background: yellow; position: relative; z-index: 10; } .right{ flex: 1; background: blue; position: relative; z-index: 5; }
|
PortalDialog.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| import React, {Component} from 'react'; import {createPortal} from "react-dom";
class PortalDialog extends Component { render() { return createPortal ( <div style={{width:'100%',height:'100%',position:'fixed',left:0,top:0,background:'rgba(0,0,0,0.7)',zIndex:9999}}> Dialog- <div>loading-正在加载中。。</div> <button onClick={this.props.onClose}>close</button> </div> ,document.body); } }
export default PortalDialog;
|
portal中的事件冒泡
虽然通过portal渲染的元素在父组件的盒子之外,但是渲染的dom节点仍在React的元素树上,在那个dom元素上的点击事件仍然能在dom树中监听到。