1. 程式人生 > 其它 >React學習筆記(五) Portal

React學習筆記(五) Portal

1、用法

普通的元件,子元件的元素將掛載到父元件的DOM節點中。

render() {
  // React 掛載一個div節點,並將子元素渲染在節點中
  return (
    <div>
      {this.props.children}
    </div>
  );
}

有時需要將元素渲染到DOM中的不同位置上去,這是就用到的portal的方法。

render(){
    // 此時React不再建立div節點,而是將子元素渲染到Dom節點上。domNode,是一個有效的任意位置的dom節點。
    return ReactDOM.createPortal(
        this.props.children,
        domNode
    )
}

一個典型的用法就是當父元件的dom元素有 overflow:hidden或者z-inde樣式,而你又需要顯示的子元素超出父元素的盒子。舉例來說,如對話方塊,懸浮框,和小提示。

2、在protal中的事件冒泡

雖然通過portal渲染的元素在父元件的盒子之外,但是渲染的dom節點仍在React的元素樹上,在那個dom元素上的點選事件仍然能在dom樹中監聽到。

//index.jsx
import React, { Component } from 'react'
import { createPortal } from 'react-dom'

import Dialog from './Dialog'

class PortalDemo extends Component {
  state = {
    show: false
  }

  open = () => {
    this.setState({
      show: true
    })
  }

  close = () => {
    console.log(0)
    this.setState({
      show: false
    })
  }
  
  render() {
    return (
      <>
        <div onClick={this.close}>
          {
            this.state.show && <Dialog></Dialog>
          }
        </div>
        <button onClick={this.open}>open</button>
      </>
    );
  }
}

class PortalDialog extends Component {
  render() {
    return createPortal(
      <PortalDemo></PortalDemo>,
      document.body
    )
  }
}

export default PortalDialog;
//Dialog.jsx
import React, { Component } from 'react';

class Dialog extends Component {
  render() {
    return (
      <div
        style={{
          position: 'fixed',
          left: 0,
          right: 0,
          top: 0,
          bottom: 0,
          background: 'rgba(0, 0, 0, 0.5)',
          display: 'flex',
          justifyContent: 'center',
          alignItems: 'center'
        }}
      >
        dialog
      </div>
    );
  }
}

export default Dialog;