Skip to main content

Overlay 通用浮层

使用场景#

通用的浮层组件。<Overlay /> 是一个较为底层的组件,一般不会单独进行使用。

Overlay 提供了 对话框抽屉弹层 等上层组件所需的共同能力,包括:

很多上层组件(例如对话框)继承了来自 Overlay 的 props 和相应功能,所以本页下方的特性介绍也适用这些上层组件。

注意 Overlay 并没有提供 定位 的能力。

特性介绍#

浮层容器#

浮层组件默认会使用 React Portal 并配合 absolute 或 fix 定位方式将内容渲染到 document.body 中。如果指定了 props.portalContainer,组件会将内容渲染到对应的容器中。rexd 组件库也提供了 OverlayBehaviorContext 用于设置浮层默认挂载节点。

在一些特殊情况下,例如「上层元素的 overflow=hidden 需要作用于浮层内容」,此时可以设置 usePortal={false} 来禁用 React Portal,组件会用常规方式来渲染浮层内容。

出现消失动画#

Overlay 封装了内容出现和消失的动画,默认动画如下:

<Overlay
animation={{
in: Overlay.animations.fadeIn,
out: Overlay.animations.fadeOut,
}}
/>

Overlay.animations 提供了 Overlay 默认支持的动画效果,例如 Overlay.animations.fadeIn。完整列表可以在 Overlay 源码中进行查看。rexd 中的动画效果与 animate.css 相兼容,你也可以引入 animate.css,然后使用 animate.css 提供的动画效果。例如:

<Overlay animation={{ in: 'backInLeft', out: 'fadeOuztDown' }} />

你可以使用与 animate.css 相同的方式来指定动画的时长和延迟:

<Overlay
style={{
'--animate-duration': '1s',
'--animate-delay': '300ms',
}}
animation={{
in: Overlay.animations.fadeIn,
out: Overlay.animations.fadeOut,
}}
/>

如果不需要使用动画,可以设置 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 将不被调用
浮层生命周期相关 TS 类型
interface IOverlayLifecycles {
beforeOpen?(state?: any): undefined | Promise<IOverlayOpenInstruction>;
onOpen?(): void;
afterOpen?(): void;
beforeClose?(): undefined | IOverlayCloseInstruction;
onRequestClose?(): void;
afterClose?(): void;
}

关闭操作与安全节点#

除了在上层主动控制浮层的显示或隐藏之外,浮层也提供了以下额外的关闭操作:

  • 设置 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#

字段描述
overlayKeystring
visible*boolean
是否显示弹层
onRequestClose(reason: any) => void
弹层请求关闭时触发事件的回调函数
classNamestring
弹层的根节点的样式类
styleCSSProperties
弹层的根节点的内联样式
childrenReactNode
弹层内容
renderChildren(pass: { ref: RefObject<Element>; children: ReactNode; }) => ReactNode = Overlay.defaultRenderChildren
使用 render prop 的形式指定弹层内容,用于精确控制 DOM 结构
wrapperRefRef<HTMLDivElement>
safeNodes(Node | (() => Node))[] = []
attachOverlayManagerboolean = true
是否关联到 portalContainer 上的 overlay manager. 该属性一般保持默认即可。
浮层交互
canCloseByEscboolean = true
是否支持 esc 按键关闭弹层
canCloseByOutSideClickboolean = true
点击弹层外部区域是否关闭弹层(注意背景层也被认为是外部)
浮层生命周期
beforeOpen(state?: any) => Promise<IOverlayAnimationProps>
浮层即将被打开时的回调
onOpen() => void
浮层打开时的回调
afterOpen() => void
浮层打开时的回调
beforeClose() => IOverlayAnimationProps
浮层即将被关闭时的回调
onClose() => void
浮层关闭时的回调
afterClose() => void
浮层关闭后的回调
背景层
hasBackdropboolean
是否展示背景层
backdropStyleCSSProperties
backdropClassNamestring
浮层动画
animationDurationstring = 200ms
动画持续时间(注意该 prop 会作为 CSS 变量的值,使用时要带上单位,例如 `'500ms'`)
animationfalse | { in: string | Keyframes; out: string | Keyframes; } = { in: animations.fadeIn, out: animations.fadeOut }
弹层的出现和消失的动画,可以用 Overlay.animations.{name} 来引用弹层组件内置的动画效果
浮层容器
usePortalboolean = true
是否使用 portal 来渲染弹层内容
portalContainerHTMLElement | "DOCUMENT_BODY"
渲染组件的容器
disableScrollboolean | "force" = false
是否禁用容器的滚动
Copyright © 2021 Alibaba Inc.
Built with ❤️ by hema-FE.