ReactJS - 端口



端口提供了一种方式,让组件可以将其子元素渲染到其自身 DOM 层次结构之外的 DOM 节点中。端口可用于模态对话框、弹出窗口、工具提示等,在这些场景中,父组件(渲染组件)和子 DOM 节点(模态对话框)最好渲染在不同的 DOM 节点中。

在本章中,我们将学习端口的工作原理以及如何在我们的应用程序中应用它。

端口的概念和用法

假设我们在主文档中有两个 DOM 节点,如下所示:

<div id='root'></div>
<div id='modalRoot'></div>

这里,根 DOM 节点将附加到主 React 组件。modalRoot 将在 React 应用需要显示模态对话框时使用,它将模态对话框附加到 modelRoot DOM 节点,而不是将其渲染到自身 DOM 元素内。

这将有助于将模态对话框与实际应用分离。将模态对话框与其父 DOM 元素分离,可以使其免受父 DOM 元素样式的影响。样式可以单独应用,因为模态对话框、工具提示等在样式方面与其父元素有所不同。

React 在 ReactDOM 包中提供了一个特殊的 createPortal 方法来创建端口。该方法的签名如下:

ReactDOM.createPortal(child, container)

这里,

  • child 是由父组件渲染的模态对话框、工具提示等。

render() {
   return ReactDOM.createPortal(
      this.props.children, // modal dialog / tooltips
      domNode // dom outside the component
   );
}
  • container 是父 DOM 节点之外的 DOM 元素(在上面的示例中为 domNode)。

应用端口

在本节中,我们将创建一个新的 React 应用来学习如何在其中应用端口。

首先,使用以下命令创建一个新的 React 应用并启动它。

create-react-app myapp
cd myapp
npm start

接下来,打开 App.css (src/App.css) 并移除所有 CSS 类,并包含模态对话框的 CSS。

.modal {
   position: absolute;
   top: 0;
   bottom: 0;
   left: 0;
   right: 0;
   display: grid;
   justify-content: center;
   align-items: center;
   background-color: rgba(0,0,0,0.2);
}
.modalContent {
   padding: 20px;
   background-color: #fff;
   border-radius: 2px;
   display: inline-block;
   min-height: 300px;
   margin: 1rem;
   position: relative;
   min-width: 300px;
   box-shadow: 0 3px 6px rgba(0,0,0,0.16), 0 3px 6px rgba(0,0,0,0.23);
   justify-self: center;
}

接下来,打开 index.html (public/index.html) 并添加一个 DOM 节点以支持端口

<!DOCTYPE html>
<html lang="en">
   <head>
      <link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
      <link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
      <link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
   </head>
   <body>
      <noscript>You need to enable JavaScript to run this app.</noscript>
      <div style="padding: 10px;">
         <div id="root"></div>
      </div>
      <div id="modalRoot"></div>
   </body>
</html>

接下来,创建一个简单的组件 SimplePortal (src/Components/SimplePortal.js) 并渲染一个模态对话框,如下所示:

import React from "react";
import PortalReactDOM from 'react-dom'
const modalRoot = document.getElementById('modalRoot')
class SimplePortal extends React.Component {
   constructor(props) {
      super(props);
   }
   render() {
      return PortalReactDOM.createPortal(
         <div
            className="modal"
            onClick={this.props.onClose}
            >
            <div className="modalContent">
               {this.props.children}
               <hr />
               <button onClick={this.props.onClose}>Close</button>
            </div>
         </div>,
         modalRoot,
      )
   }
}
export default SimplePortal;

这里,

  • createPortal 用于创建一个新的端口并渲染一个模态对话框。

  • 模态对话框的内容通过 this.props.children 从组件的子元素中获取。

  • 关闭按钮操作通过 props 处理,并将由父组件处理。

接下来,打开 App 组件 (src/App.js),并使用 SimplePortal 组件,如下所示:

import './App.css'
import React from 'react';
import SimplePortal from './Components/SimplePortal'
class App extends React.Component {
   constructor(props) {
      super(props);
      this.state = { modal: false }
   }
   handleOpenModal = () => this.setState({ modal: true })
   handleCloseModal = () => this.setState({ modal: false })
   render() {
      return (
         <div className="container">
            <div style={{ padding: "10px" }}>
               <div>
                  <div><p>Main App</p></div>
                  <div>
                     <button onClick={this.handleOpenModal}>
                        Show Modal
                     </button>
                     { this.state.modal ? (
                        <SimplePortal onClose={this.handleCloseModal}>
                           Hi, I am the modal dialog created using portal.
                        </SimplePortal>
                     ) : null}
                  </div>
               </div>
            </div>
         </div>
      );
   }
}
export default App;

这里,

  • 导入了 SimplePortal 组件

  • 添加了一个按钮来打开模态对话框

  • 创建了一个处理程序来打开模态对话框

  • 创建了一个处理程序来关闭模态对话框,并将其通过 onClose props 传递给 SimplePortal 组件。

最后,在浏览器中打开应用程序并检查最终结果。

ReactJS Portals

总结

React 端口提供了一种简单的方法来访问和处理组件外部的 DOM。它能够在不同的 DOM 节点之间轻松地进行事件冒泡。

广告