ReactJS - createPortal() 方法



React 门户允许我们将网站的某些部分移动到屏幕上的不同位置。它们对于各种活动都很有用,例如显示弹出框或将材料插入页面的特定部分。

createPortal 是一个 React 函数,它允许我们在网站上移动项目。假设我们的网站上有一个框,我们希望某些内容出现在该框内的页面的不同位置。这就是createPortal的用武之地。

语法


<div>
	 	<MyComponent />
	 	{createPortal(children, domNode, key!)}
</div>

参数

  • children - 我们想要显示的任何内容,例如文本、图片或我们网站的其他部分。
  • domNode - 我们希望内容在页面上出现的位置。它可能是整个页面,也可能只是其中的一部分。
  • key - 这是一个额外的代码,将帮助 React 跟踪事情。这通常留空。

返回值

当我们使用 createPortal 时,我们会得到一些特殊的东西作为回报。这个特殊的对象类似于一张魔术卡,我们可以将其插入到我们的代码中,React 将知道在哪里显示我们的内容。

例子

让我们通过创建小型 React 应用程序来查看 createPortal 的不同示例。

示例 1

此应用程序显示一个按钮。当我们单击该按钮时,屏幕上会显示一个称为“模态”的特殊窗口。模态就像一个包含一些信息或选项的小盒子。我们可以通过单击其中的一个小“x”来关闭模态。

AppModal.js


import React from 'react';
import { createPortal } from 'react-dom';

const AppModal = ({ isOpen, onClose }) => {
	 	const modalRoot = document.getElementById('modal-root'); 		
	 	if (!modalRoot) {
	 	 	 console.error("Modal root container not found in the DOM.");
	 	 	 return null;
	 	} 		
	 	return isOpen ? createPortal(
	 	 	 <div className="modal App">
	 	 	 	 	<div className="modal-content">
	 	 	 	 	 	 <span className="close" onClick={onClose}>×</span>
	 	 	 	 	 	 <p>This is a modal!</p>
	 	 	 	 	</div>
	 	 	 </div>,
	 	 	 modalRoot
	 	) : null;
};

export default AppModal;

index.html


<!DOCTYPE html>
<html lang="en">
<head>
	 	<meta charset="utf-8" />
	 	<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
	 	<meta name="viewport" content="width=device-width, initial-scale=1" />
	 	<meta name="theme-color" content="#000000" />
	 	<meta
	 	name="description"
	 	content="Web site created using create-react-app"
	 	/>
	 	<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
	 	<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
	 	<title>React App</title>
</head>
<body>
	 	<div id="root"></div>
	 	<div id="modal-root"></div>
</body>
</html>

App.js


import React, { useState } from 'react';
import AppModal from './AppModal';
import './App.css';

const App = () => {
	 	const [modalOpen, setModalOpen] = useState(false); 		
	 	const handleOpenModal = () => setModalOpen(true);
	 	const handleCloseModal = () => setModalOpen(false); 		
	 	return (
	 	 	 <div className='App'>
	 	 	 	 	<h1>Modal</h1>
	 	 	 	 	<button onClick={handleOpenModal}>Open Modal</button>
	 	 	 	 	<AppModal isOpen={modalOpen} onClose={handleCloseModal} />
	 	 	 </div>
	 	);
};

export default App;

输出

开放模态

有一个名为“打开模式”的按钮。当我们单击该按钮时,会出现一个模态,其中包含一条消息。要关闭模态,我们可以单击左侧的“x”。

示例 2

这个应用程序有一个按钮,当我们将鼠标悬停在按钮上时,会出现一个包含额外信息的小框。这个小框被称为“工具提示”。它为我们提供了有关该按钮的更多详细信息。

AppTooltip.js


import React from 'react';
import { createPortal } from 'react-dom';
import './App.css';

const AppTooltip = () => {
	 	const tooltipRoot = document.getElementById('tooltip-root'); 		
	 	if (!tooltipRoot) {
	 	 	 console.error("Tooltip root container not found in the DOM.");
	 	 	 return null;
	 	} 		
	 	return createPortal(
	 	 	 <div className="tooltip App">
	 	 	 	 	<p>This is a tooltip!</p>
	 	 	 </div>,
	 	 	 tooltipRoot
	 	);
};

export default AppTooltip;

index.html


<!DOCTYPE html>
<html lang="en">
<head>
	 	<title>React App</title>
</head>
<body>
	 	<div id="root"></div>
	 	<div id="tooltip-root"></div>
</body>
</html>

App.js


import React from 'react';
import AppTooltip from './AppTooltip';
import './App.css';

const App = () => {
	 	return (
	 	 	 <div className='App'>
	 	 	 	 	<h1>Tooltip App</h1>
	 	 	 	 	<button>Hover me</button>
	 	 	 	 	<AppTooltip />
	 	 	 </div>
	 	);
};

export default App;

输出

工具提示应用

有一个按钮,我们可以将鼠标悬停在上面。当我们将鼠标悬停在按钮上时,会出现一个包含信息的小框。这个框是工具提示,当我们移开鼠标时,它就会消失。

示例 3

在这个应用程序中,有一个特殊的组件似乎漂浮在页面上。它就像一个小盒子,里面的信息即使我们滚动页面也会保持在一个地方。这对于我们希望人们始终看到的重要细节非常有用。

AppFloatingComponent.js


import React from 'react';
import { createPortal } from 'react-dom';

const AppFloatingComponent = () => {
	 	const floatingRoot = 	 	document.getElementById('floating-root'); 		
	 	return createPortal(
	 	 	 <div className="floating-component">
	 	 	 	 	<p>This is a floating component!</p>
	 	 	 </div>,
	 	 	 floatingRoot
	 	);
};

export default AppFloatingComponent;

index.html


<div id="floating-root"></div>

App.js


import React from 'react';
import AppFloatingComponent from './AppFloatingComponent';
import './App.css';

const App = () => {
	 	return (
	 	 	 <div className='App'>
	 	 	 	 	<h1>Floating Component</h1>
	 	 	 	 	<AppFloatingComponent />
	 	 	 </div>
	 	);
};

export default App;

输出

浮动组件

有一个包含信息的框,这些信息位于页面上的一个位置。即使我们向上或向下滚动,该框仍然可见。

这对于显示我们希望人们一直看到的重要信息非常方便。

局限性

使用门户时,事件(如点击)可能会以不同的方式发生。如果我们发现问题,我们可以从门户内部解决它们,也可以在我们的网页系列中重新定位门户。

总结

React 门户就像神奇的门,让我们可以更好地构建我们的网站。使用 createPortal,我们能够重新排列元素,使我们的网站看起来完全符合我们的要求。