Portal传送门 #
一、Portal 概述 #
1.1 什么是 Portal #
Portal 允许将子元素渲染到 DOM 树中的不同位置,而不是父组件内部。
jsx
import { Portal } from 'solid-js/web';
function Modal() {
return (
<Portal>
<div class="modal">Modal Content</div>
</Portal>
);
}
1.2 Portal 用途 #
| 用途 | 说明 |
|---|---|
| 模态框 | 避免 z-index 和 overflow 问题 |
| 下拉菜单 | 防止被父容器裁剪 |
| 工具提示 | 确保正确显示位置 |
| 通知消息 | 全局显示位置 |
二、基本用法 #
2.1 渲染到 body #
jsx
import { Portal } from 'solid-js/web';
function App() {
const [show, setShow] = createSignal(false);
return (
<div>
<button onClick={() => setShow(true)}>Open Modal</button>
<Show when={show()}>
<Portal>
<div class="modal-overlay" onClick={() => setShow(false)}>
<div class="modal-content">
<h2>Modal Title</h2>
<button onClick={() => setShow(false)}>Close</button>
</div>
</div>
</Portal>
</Show>
</div>
);
}
2.2 指定挂载点 #
jsx
<Portal mount={document.getElementById('modal-root')}>
<div class="modal">Modal Content</div>
</Portal>
三、实际应用 #
3.1 模态框组件 #
jsx
function Modal(props) {
return (
<Portal>
<div class="modal-overlay" onClick={props.onClose}>
<div class="modal-content" onClick={(e) => e.stopPropagation()}>
<div class="modal-header">
<h2>{props.title}</h2>
<button onClick={props.onClose}>×</button>
</div>
<div class="modal-body">{props.children}</div>
</div>
</div>
</Portal>
);
}
3.2 下拉菜单 #
jsx
function Dropdown(props) {
const [isOpen, setIsOpen] = createSignal(false);
let buttonRef;
return (
<>
<button ref={buttonRef} onClick={() => setIsOpen(!isOpen())}>
{props.label}
</button>
<Show when={isOpen()}>
<Portal>
<div class="dropdown">
<For each={props.items}>
{(item) => <div onClick={item.onClick}>{item.label}</div>}
</For>
</div>
</Portal>
</Show>
</>
);
}
四、最佳实践 #
- 确保 Portal 内容有正确的 z-index
- 处理键盘事件(如 ESC 关闭)
- 点击外部关闭模态框
- 阻止事件冒泡
五、总结 #
5.1 Portal API #
| 属性 | 说明 |
|---|---|
mount |
指定挂载点 |
ref |
获取 Portal 引用 |
children |
Portal 内容 |
5.2 使用场景 #
- 模态框和对话框
- 全局通知
- 下拉菜单
- 工具提示
最后更新:2026-03-28