ReactJS 教程

ReactJS - 主页 ReactJS - 简介 ReactJS - 路线图 ReactJS - 安装 ReactJS - 功能 ReactJS - 优势和缺点 ReactJS - 架构 ReactJS - 创建 React 应用程序 ReactJS - JSX ReactJS - 组件 ReactJS - 嵌套组件 ReactJS - 使用组件 ReactJS - 集合组件 ReactJS - 样式 ReactJS - 属性 (props) ReactJS - 使用属性创建组件 ReactJS - props 验证 ReactJS - 构造函数 ReactJS - 组件生命周期 ReactJS - 事件管理 ReactJS - 创建事件感知组件 ReactJS - Expense Manager 事件 ReactJS - 状态管理 ReactJS - 状态管理 API ReactJS - 无状态组件 ReactJS - Hooks 进行状态管理 ReactJS - Hooks 的组件生命周期 ReactJS - 布局组件 ReactJS - 分页 ReactJS - Material UI ReactJS - Http 客户端编程 ReactJS - 表单编程 ReactJS - 受控组件 ReactJS - 非受控组件 ReactJS - Formik ReactJS - 条件渲染 ReactJS - 列表 ReactJS - Key 键 ReactJS - 路由 ReactJS - Redux ReactJS - 动画 ReactJS - Bootstrap ReactJS - Map ReactJS - 表格 ReactJS - 使用 Flux 管理状态 ReactJS - 测试 ReactJS - CLI 命令 ReactJS - 构建和部署 ReactJS - 示例

Hooks

ReactJS - Hooks 简介 ReactJS - 使用 useState ReactJS - 使用 useEffect ReactJS - 使用 useContext ReactJS - 使用 useRef ReactJS - 使用 useReducer ReactJS - 使用 useCallback ReactJS - 使用 useMemo ReactJS - 自定义 Hooks

ReactJS 高级

ReactJS - 可访问性 ReactJS - 代码拆分 ReactJS - 上下文 ReactJS - 错误边界 ReactJS - 转发 Refs ReactJS - 片段 ReactJS - 高阶组件 ReactJS - 与其他库集成 ReactJS - 优化性能 ReactJS - Profiler API ReactJS - Portals ReactJS - 不使用 ES6 ECMAScript ReactJS - 不使用 JSX 的 React ReactJS - Reconciliation ReactJS - Refs 和 DOM ReactJS - 渲染道具 ReactJS - 静态类型检查 ReactJS - 严格模式 ReactJS - Web 组件

其他概念

ReactJS - 日期选择器 ReactJS - Helmet ReactJS - 内联样式 ReactJS - PropTypes ReactJS - BrowserRouter ReactJS - DOM ReactJS - 轮播 ReactJS - 图标 ReactJS - 表单组件 ReactJS - 参考 API

ReactJS 有用资源

ReactJS - 快速指南 ReactJS - 备忘录 Axios - 备忘录 ReactJS - 有用资源 ReactJS - 讨论


ReactJS - Portals

Portals 为组件提供了一种将其子组件渲染到其自身 DOM 层次结构之外的 DOM 节点中的方法。Portal 可用于模型对话框、弹出窗口、工具提示等,其中父组件(渲染组件)和子 DOM 节点(模型对话框)最好在不同的 DOM 节点中渲染。

让我们在本章中了解门户的工作原理以及如何在我们的应用程序中应用它。

门户的概念和用法

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

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

此处,根 DOM 节点将与主 React 组件连接。React 应用程序需要显示模态对话框时,将使用 modalRoot,方法是将模态对话框附加到 modelRoot DOM 节点中,而不是在其自己的 DOM 元素内渲染模型对话框。

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

React 在 ReactDOM 包中提供了一种特殊的方法 createPortal 来创建门户。方法签名如下 −

ReactDOM.createPortal(child, container)

这里,

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

render() {
    return ReactDOM.createPortal(
        this.props.children, // 模态对话框/工具提示
        domNode // 组件外部的 dom
    );
}
  • container 是父 DOM 节点(上例中的 domNode)之外的 DOM 元素

应用门户

让我们创建一个新的 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 portal 提供了一种在组件外部访问和处理 DOM 的简便方法。它使事件在不同的 DOM 节点之间冒泡,而无需任何额外的努力。