天天看點

React 傳送門【Portal】

文章目錄

    • Portal
      • Portal的用法
      • 在Portal中的事件冒泡

Portal

  • Portal 提供了一個最好的在父元件包含的DOM結構層級外的DOM節點渲染元件的方法
  • render到一個元件中時,實際上是改變了網頁上的另一處的dom結構,一般用于對話框、提示框
  • ReactDOM.createPortal(child,container);

  • child

    :可渲染的react子項,比如元素,字元串或片段
  • container

    :DOM元素

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')
)
           
React 傳送門【Portal】
React 傳送門【Portal】