Overlay 通用浮层
使用场景#
通用的浮层组件。<Overlay /> 是一个较为底层的组件,一般不会单独进行使用。
Overlay 提供了 对话框、抽屉、弹层 等上层组件所需的共同能力,包括:
- 浮层容器
usePortal&portalContainer - 出现消失动画
animation - 浮层生命周期
beforeOpen&onOpen... - 关闭操作与安全节点
canCloseBy*&safeNodes - 禁止容器滚动
disableScroll - 背景层
hasBackdrop
很多上层组件(例如对话框)继承了来自 Overlay 的 props 和相应功能,所以本页下方的特性介绍也适用这些上层组件。
注意 Overlay 并没有提供 定位 的能力。
特性介绍#
浮层容器#
浮层组件默认会使用 React Portal 并配合 absolute 或 fix 定位方式将内容渲染到 document.body 中。如果指定了 props.portalContainer,组件会将内容渲染到对应的容器中。rexd 组件库也提供了 OverlayBehaviorContext 用于设置浮层默认挂载节点。
在一些特殊情况下,例如「上层元素的 overflow=hidden 需要作用于浮层内容」,此时可以设置 usePortal={false} 来禁用 React Portal,组件会用常规方式来渲染浮层内容。
出现消失动画#
Overlay 封装了内容出现和消失的动画,默认动画如下:
Overlay.animations 提供了 Overlay 默认支持的动画效果,例如 Overlay.animations.fadeIn。完整列表可以在 Overlay 源码中进行查看。rexd 中的动画效果与 animate.css 相兼容,你也可以引入 animate.css,然后使用 animate.css 提供的动画效果。例如:
你可以使用与 animate.css 相同的方式来指定动画的时长和延迟:
如果不需要使用动画,可以设置 animation={false}。
浮层生命周期#
围绕浮层的打开和关闭,Overlay 提供了以下六个声明周期回调:
beforeOpen浮层即将被打开时的回调- 该回调函数可以返回一个类型为
{ animation: { in: xx, out: yy } }的 Promise 来设置「本次打开所使用的动画效果」 - 如果函数没有返回值,则使用
props.animation.in作为「本次打开所使用的动画效果」
- 该回调函数可以返回一个类型为
onOpen浮层打开时的回调,此时相关 DOM 元素中已经设置了 CSS animation,动画即将开始afterOpen浮层打开后的回调,此时动画效果已经结束beforeClose浮层即将被关闭时的回调- 该回调函数可以返回一个类型为
{ animation: { in: xx, out: yy } }的 普通对象 来设置「本次关闭所使用的动画效果」 - 如果函数没有返回值,则使用
props.animation.out作为「本次关闭所使用的动画效果」
- 该回调函数可以返回一个类型为
onClose浮层关闭时的回调,此时相关 DOM 元素中已经设置了 CSS animation,动画即将开始afterClose浮层关闭后的回调,此时动画效果已经结束- 如果浮层组件在打开状态下发生了卸载(unmount),afterClose 将不被调用
关闭操作与安全节点#
除了在上层主动控制浮层的显示或隐藏之外,浮层也提供了以下额外的关闭操作:
- 设置
canCloseByEsc={true}后,按下 ESC 键关闭最近打开的浮层 - 设置
canCloseByOutSideClick={true}后,点击浮层外节点关闭最近打开的浮层- 如果想让某个节点点击后不关闭浮层弹层(如:触发浮层打开的按钮),请将该节点加入到
safeNodes中。
- 如果想让某个节点点击后不关闭浮层弹层(如:触发浮层打开的按钮),请将该节点加入到
注意:
- canClose* 需要配合 onRequestClose 才能关闭弹层
- canClose* 一次只能关闭一个浮层,同时关闭多个浮层需要通过其他方式
禁止容器滚动#
设置了 disableScroll={true} 的浮层被打开后,会给 portalContainer 追加额外的样式来禁用容器上的滚动。
多个浮层被同时打开时,只要有一个浮层设置了 disableScroll={true},容器的滚动就会被禁止。
如果容器没有按照预期禁用滚动,可以设置 disableScroll="force",此时组件将为容器附加 overflow: hidden !important; 的 CSS 样式。
背景层#
设置了 hasBackdrop={true} 的浮层被打开后,会在 portalContainer 上渲染传一个额外的背景层。
所有浮层的「背景层」和「浮层内容」的 z-index 默认值均为 1000,多个浮层被同时打开时,新打开的浮层会展示在已有浮层之上。
API#
| 字段 | 描述 | |
|---|---|---|
| overlayKey | string | |
| visible* | boolean是否显示弹层 | |
| onRequestClose | (reason: any) => void弹层请求关闭时触发事件的回调函数 | |
| className | string弹层的根节点的样式类 | |
| style | CSSProperties弹层的根节点的内联样式 | |
| children | ReactNode弹层内容 | |
| renderChildren | (pass: { ref: RefObject<Element>; children: ReactNode; }) => ReactNode = Overlay.defaultRenderChildren使用 render prop 的形式指定弹层内容,用于精确控制 DOM 结构 | |
| wrapperRef | Ref<HTMLDivElement> | |
| safeNodes | (Node | (() => Node))[] = [] | |
| attachOverlayManager | boolean = true是否关联到 portalContainer 上的 overlay manager. 该属性一般保持默认即可。 | |
| 浮层交互 | ||
| canCloseByEsc | boolean = true是否支持 esc 按键关闭弹层 | |
| canCloseByOutSideClick | boolean = true点击弹层外部区域是否关闭弹层(注意背景层也被认为是外部) | |
| 浮层生命周期 | ||
| beforeOpen | (state?: any) => Promise<IOverlayAnimationProps>浮层即将被打开时的回调 | |
| onOpen | () => void浮层打开时的回调 | |
| afterOpen | () => void浮层打开时的回调 | |
| beforeClose | () => IOverlayAnimationProps浮层即将被关闭时的回调 | |
| onClose | () => void浮层关闭时的回调 | |
| afterClose | () => void浮层关闭后的回调 | |
| 背景层 | ||
| hasBackdrop | boolean是否展示背景层 | |
| backdropStyle | CSSProperties | |
| backdropClassName | string | |
| 浮层动画 | ||
| animationDuration | string = 200ms动画持续时间(注意该 prop 会作为 CSS 变量的值,使用时要带上单位,例如 `'500ms'`) | |
| animation | false | { in: string | Keyframes; out: string | Keyframes; } = { in: animations.fadeIn, out: animations.fadeOut }弹层的出现和消失的动画,可以用 Overlay.animations.{name} 来引用弹层组件内置的动画效果 | |
| 浮层容器 | ||
| usePortal | boolean = true是否使用 portal 来渲染弹层内容 | |
| portalContainer | HTMLElement | "DOCUMENT_BODY"渲染组件的容器 | |
| disableScroll | boolean | "force" = false是否禁用容器的滚动 | |
