Live2D

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;
posted @ 2021-08-19 17:05  吃完夜宵再睡觉  阅读(170)  评论(0)    收藏  举报