paint-brush
如何使用 React Portal 将组件传输到任何地方经过@smpnjn
1,997 讀數
1,997 讀數

如何使用 React Portal 将组件传输到任何地方

经过 Johnny Simpson5m2022/10/12
Read on Terminal Reader
Read this story w/o Javascript

太長; 讀書

当我们在 React 中创建组件时,它们通常存在于组件树中。这通常很好,但有时我们希望组件的某些部分出现在树之外。使用`createPortal,我们可以将模态从它自己的组件传送到我们模板的另一部分。这允许我们将组件放置在我们想要的任何其他位置,例如 HTML 树的基础、`body` 标记内或另一个元素内。使用 React Portals 很容易创建一个门户。

Company Mentioned

Mention Thumbnail
featured image - 如何使用 React Portal 将组件传输到任何地方
Johnny Simpson HackerNoon profile picture

当我们在 React 中创建组件时,它们通常存在于组件树中。这大部分都很好,但有时我们希望组件的某些部分出现在组件树之外,或者完全不同的地方。


这是我们创建模态弹出窗口时的常见要求,它需要高于所有其他组件。


我们可以在一个组件中创建它们,但最终我们希望它们高于一切,并且将它们嵌套在许多组件中可能会导致问题,因为它们的z-index将低于它们所在的位置:


反应组件图

为了解决这个问题,我们可以使用createPortal将模态从它自己的组件中传送到模板的另一部分。


这允许我们将组件放置在我们想要的任何其他位置,例如 HTML 树的基础、 body标签内或另一个元素内。


即使元素存在于组件树中, createPortal也让我们能够将它放在我们喜欢的任何位置。

使用 React 门户

为了向您展示门户是如何工作的,请考虑我们的App.js文件中有以下基本 React 代码。在这里,我们希望模态显示在其他所有内容之上。因此,我们创建了一个名为#modal-containerdiv 。这最终是我们希望所有模态进入的地方:


 import logo from './logo.svg'; import './App.css'; import { useState } from 'react' import Modal from './components/Modal.js'; function App() { const [isModalOpen, setIsModalOpen] = useState(false); return ( <div className="App"> <header className="App-header"> <img src={logo} className="App-logo" alt="logo" /> <p> Edit <code>src/App.js</code> and save to reload. </p> <button onClick={() => setIsModalOpen(!isModalOpen)}> Click to Open Modal </button> <Modal modalState={isModalOpen} onClickEvent={() => setIsModalOpen(!isModalOpen)}> This is Modal Content! </Modal> </header> <div id="modal-container"></div> </div> ); } export default App;


App.js中,我导入了一个名为Modal的组件。这是我们的 Modal 组件,它会在用户单击按钮时弹出。


每当使用setIsModalOpen()isModalOpen设置为 true 时,应该出现模式。否则,它会消失。


我还有一些 CSS 来确保我们的模态确实出现在其他所有内容之上:


 #modal-container { position: absolute; top: 0; left: 0; width: 100%; z-index: 9999; height: 100%; pointer-events: none; } .modal { position: absolute; top: 200px; background: white; border-radius: 4px; left: calc(50% - 100px); width: 200px; }

创建我们的 {ortal

创建门户非常简单 - 有一个函数createPortal() 。我们没有在 React 中返回一些 DOM,而是返回Portal


createPortal()接受两个参数——我们想要返回的 DOM 元素——在本例中是模态元素——以及我们想要将 DOM 元素传送到的 DOM 元素。


因此,我们的第二个参数是document.getElementById('modal-container') ,因为我们想将所有模态放入#modal-container


 import { createPortal } from 'react-dom'; function Modal({modalState, onClickEvent}) { if(!modalState) return null; return ( createPortal( <div className="modal"> <button onClick={onClickEvent}>Close Modal</button> <div className="modal-content">Modal Content goes here</div> </div>, document.getElementById('modal-container') ) ); }; export default Modal;


尽管我们将 DOM 元素传送到了modal-container ,但它的行为仍然像一个普通的 React 子元素。由于 Portal 仍然存在于 React 树中,因此元素所在的上下文等功能仍然可以正常工作。


还应该注意的是,虽然我们在同一个文件中有modal-containerModal ,但你传送 DOM 元素的位置可以是 React 代码中的任何位置


因此,您可以将其传送到 DOM 中任何位置的完全不同的子组件、元素或父组件。它非常强大和有用 - 所以要明智地使用它。


让我们回顾一下我们的App.js HTML:


 <!-- .... --> <button onClick={() => setIsModalOpen(!isModalOpen)}> Click to Open Modal </button> <Modal modalState={isModalOpen} onClickEvent={() => setIsModalOpen(!isModalOpen)}> This is Modal Content! </Modal> </header> <div id="modal-container"></div>


现在,即使Modal位于我们的标题中,只要我们使用按钮打开 modal,它也会出现在#modal-container中:

门户如何在 React 中工作

结论

门户是 React 中一个非常强大的工具。它们是解决基于组件的系统的主要问题的有用方法 - 传输某些元素高于其他所有元素。


因此,我希望你喜欢这个 React 门户指南。如果您正在学习 React,我建议您先掌握 Javascript - 您可以使用我的完整Javascript 手册来完成。


祝你有美好的一天。