Portal 提供了一种将子节点渲染到存在于父组件以外的 DOM 节点的优秀的方案
Portal 语法
/*
* 参数:
* 1. children:可以渲染的任何内容,如 JSX 片段、字符串或数字,以及这些内容构成的数组
* 2. domNode:某个已经存在的 DOM 节点,在更新过程中传递不同的 DOM 节点将导致 portal 内容被重建
* 3. key:用作 portal key 的独特字符串或数字
* 返回值:该函数返回一个 React 元素
*/
ReactDOM.createPortal(children, domNode, key?);
Portal 案例
-
示例代码:
HTMLJavaScriptJavaScript<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <title>React App</title> <style> .modal { position: fixed; left: 0; top: 20%; width: 100%; height: 80%; background: rgba(0, 0, 0, .5); } </style> </head> <body> <div id="root"></div> <div class="modal"></div> </body> </html>
import React from "react"; import ReactDOM from "react-dom"; import App from "./App"; ReactDOM.render(<App />, document.getElementById("root"));
import React from "react"; import ReactDOM from "react-dom"; function ChildA() { return ReactDOM.createPortal( <div className="child-a" style={{ marginTop: 200 }}> <h1>ChildA</h1> </div>, document.querySelector(".modal") ); } export default function App() { return ( <div className="app"> <h1>App</h1> <ChildA /> </div> ); }
-
效果展示
注意事件冒泡
-
React 中的事件是包装过的,它的事件冒泡是根据虚拟 DOM 树来冒泡的,与真实的 DOM 树无关;
import React from "react"; import ReactDOM from "react-dom"; function ChildA() { return ReactDOM.createPortal( <div className="child-a" style={{ marginTop: 200 }}> <h1>ChildA</h1> <ChildB /> </div>, document.querySelector(".modal") ); } function ChildB() { return ( <div className="child-b"> <h1>ChildB</h1> </div> ); } export default function App() { return ( <div className="app" onClick={(e) => { console.log("App被点击了", e.target); }} > <h1>App</h1> <ChildA /> </div> ); }
-
所以在点击 ChildA、ChildB 后会触发根节点的 click 点击事件;
React✍️ 渲染属性 (Render Props)
上一篇