文章目录
-
- Portal
-
- Portal的用法
- 在Portal中的事件冒泡
Portal
- Portal 提供了一个最好的在父组件包含的DOM结构层级外的DOM节点渲染组件的方法
- render到一个组件中时,实际上是改变了网页上的另一处的dom结构,一般用于对话框、提示框
-
ReactDOM.createPortal(child,container);
-
:可渲染的react子项,比如元素,字符串或片段child
-
:DOM元素container
Portal的用法
- 普通的组件,子组件的元素将挂载到父组件的DOM节点中
render(){
// React 挂载一个 div 节点,并将子元素渲染到节点中
<div>{this.props.children}</div>
}
- 如果需要将元素渲染到DOM中的不同位置上去,这是就要用到
的方法Portal
render(){
// 此时React不再创建div节点,而是将子元素渲染到Dom节点上。domNode,是一个有效的任意位置的dom节点
return ReactDom.createPortal(
this.props.children,
domNode
)
}
一个典型的用法就是当父组件的dom元素有或
overflow:hidden
z-index
样式,而你又需要显示的子元素超出父元素的盒子。
举例来说,如对话框,悬浮框,和小提示。
在Portal中的事件冒泡
虽然通过 portal 渲染的元素在父组件的盒子之外,但是渲染到 dom 节点仍在 React 的元素树上,在那个 dom 元素上的点击事件仍然在 dom 树中监听到。
-
文件withPortal.jsx
// 弹框的高阶组件
import React, {Component} from 'react';
import { createPortal } from 'react-dom';
const withPoract = (WrappedComponent) =>{
return class extends Component{
render(){
//创建 Portal ,参数:第一个,将要渲染的组件,第二个,将组件渲染到的位置
return(
createPortal(<WrappedComponent {...this.props} />, document.querySelector('body'))
)
}
}
}
export default withPoract;
-
文件Modal.jsx
import React, {Component} from 'react';
import withPortal from './withPortal';
import './style.css';
class Model extends Component{
constructor(props){
super(props);
this.state = {};
}
render(){
return(
<div className='portal'>
<div>我的对话框</div>
<button>添加</button>
</div>
)
}
}
export default withPortal(Model);
-
文件style.css
div.portal{
position: absolute;
left:0;
top:0;
bottom:0;
right:0;
background:rgba(0, 0, 0, 0.5);
z-index:1000;
}
-
文件App.jsx
import React, {Component} from 'react';
import Modal from './Modal';
class App extends Component{
constructor(props){
super(props);
this.state = {count:0}
}
handleClick = ()=>{
console.log(666);
this.setState({count:10});
}
render(){
// 因为 冒泡的存在,所以,即使,Modal的渲染被绑定到其他位置,
// 但是 <Modal /> 还是在根节点下面的,所以事件冒泡是存在的
return(
<div onClick={this.handleClick}>
根节点,希望在根节点上,显示对话框
num:{this.state.count}
<Modal />
</div>
)
}
}
export default App;
-
文件index.js
import ReactDOM from 'react-dom'
import App from './Protal/App';
ReactDOM.render(
<App />,
document.getElementById('root')
)
