(React) 将内部React节点挂载到外部: Portal

目的: 想把<Modal /> 深层嵌套React组件中的一个小节点,可以挂载到 #modal-root 上。

方法: 用到了Portal, 它是React的内置功能,无需引入其他库, 直接使用。

步骤: 

先封装一个简单的Portal组件

import * as React from 'react';

interface PortalProps {
  children: React.ReactNode;
  containerId: string; // 挂载的目标容器 ID
}

const Portal: React.FC<PortalProps> = ({ children, containerId }) => {
  const [container, setContainer] = React.useState<HTMLElement | null>(null);

  React.useEffect(() => {
    const el = document.getElementById(containerId);
    if (el) {
      setContainer(el);
    }
  }, [containerId]);

  if (!container) return null;

  return ReactDOM.createPortal(children, container);
};

export default Portal;

 

在自己的React组件中使用:

// ...
import Portal from './Portal'; // 替换为你实际的路径

render(): React.ReactNode {

    return (
        <div>
            {/* ... 已有 render 内容 */}

            {/* 使用 Portal 将部分节点挂载到外部 DOM id为parent_id_666的dom里 */}
            <Portal containerId="modal-root">
                <div className="demo">
                    这是自己的小节点内容
                </div>
            </Portal>
        </div>
    );
}

 

总结Portal : 

1. 脱离当前组件结构渲染

    允许将组件渲染到 任意 DOM 节点,而不受当前组件层级限制。

    特别适用于需要挂载到页面其他位置的内容(如弹窗、浮层、提示框等)

  2. 样式隔离与布局自由

    渲染后的内容不受父组件 CSS 样式影响(如 overflow:hidden),避免布局错乱。

    可以更自由地控制元素在页面中的实际位置。

  3. 保持 React 组件树逻辑一致性

    尽管内容被挂载到了别的地方,但它仍然是 React 组件树的一部分。

    状态、props、事件冒泡等机制依然正常工作。

  4. 解决 z-index 层级问题

    常用于弹窗、菜单、tooltip 等需要高 z-index 的场景。

    避免因为父容器的 overflow 或 z-index 设置导致遮挡问题。

  5. 提升用户体验

    更好地控制 DOM 插入顺序和位置,有助于实现复杂的 UI 动画或交互效果。如:全屏遮罩、浮动按钮、全局通知等。

posted @ 2025-05-28 17:31  yuxiaoliu  阅读(48)  评论(0)    收藏  举报