跳到主要内容

createPortal

一、认识


ReactDOM.createPortal() 传送门,用于创建portalPortal将提供一种将子节点渲染到DOM节点中的方式,该节点存在于DOM组件的层次结构之外。portal 只改变 DOM 节点的所处位置。在其他方面,渲染至 portalJSX 的行为表现与作为 React 组件的子节点一致。该子节点可以访问由父节点树提供的 context 对象、事件将从子节点依循 React 树冒泡到父节点。

二、语法


import { createPortal } from 'react-dom';

function App(){
return <div>
<div>按钮</div>
{
createPortal(children, domNode, key?)
}
</div>
}
  • children: React 可以渲染的任何内容,如 JSX 片段(<div /><SomeComponent /> 等等)、Fragment<>...</>)、字符串或数字,以及这些内容构成的数组。

  • domNode: 某个已经存在的 DOM 节点,例如由 document.getElementById() 返回的节点。在更新过程中传递不同的 DOM 节点将导致 portal 内容被重建。

  • key: 用作 portal key 的独特字符串或数字。

三、返回值


createPortal 返回一个可以包含在 JSX 中或从 React 组件中返回的 React 节点。如果 React 在渲染输出中遇见它,它将把提供的 children 放入提供的 domNode 中。

四、应用场景


4.1 Model 弹窗

class 组件写法

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

export default class MyDialog extends React.Component {
constructor(props) {
super(props);
if (!this.node) {
this.node = document.createElement("div");
this.node.classList = ["my-dialog"];
document.body.appendChild(this.node);
}
}
componentWillUnmount() {
this.node && this.node.remove();
}
render(){
return createPortal(<div>我的弹窗</div>,this.node);
}
}

hooks 组件写法

import React, { useEffect } from "react";
import { createPortal } from "react-dom";

export default function MyDialog() {
let node = document.createElement("div");
node.classList = ["my-dialog"];
document.body.appendChild(node);
useEffect(() => {
return () => {
node && node.remove();
};
}, []);
return createPortal(<div>我的弹窗</div>, node);
}