文章目錄
-
- 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')
)
