Overlay 弹层

如果项目中使用的是 0.x 版本的基础组件(@icedesign/base, @ali/ice, @alife/next),请在左侧导航顶部切换组件版本。

安装方法

  1. 在命令行中执行以下命令npm install @alifd/next@latest -S

用于生成弹层的工具类集合.

开发指南

Overlay 提供了一系列组件用于创建弹层。其中包含:

Overlay

Overlay 可以在页面中弹出一个浮层,封装了定位,动画及其他一些可用性的功能。Overlay 被设计为无状态的组件,其本身并不控制自己显示和隐藏的状态。

注意: 类似 canCloseby* 的配置也需要配合 onRequestClose 才能关闭弹层。

安全节点

Overlay 提供了点击弹层外文档中节点隐藏该弹层的功能,如果想让某个节点点击后不隐藏弹层(如:触发弹层打开的节点),请将该节点传入 safeNode 属性。

定位

  • align 的值可以是由空格隔开的字符串,如 tl bl,其中 tl 代表目标元素的左上方,bl 代表基准元素的左下方,所以 tl bl 的意思是目标元素的左上方对齐基准元素左下方。其中定位的可选值有 tl, tc, tr, cl, cc, cr, bl, bc, brttop 的缩写,bbottom 的缩写,ccenter 的缩写,lleft 的缩写,rright 的缩写.

  • align 支持的 Boolean 值仅为 false,在设置为 false 时,不使用 JS 定位,这样你可以根据你的需要传入 style 或者 className 进行 CSS 定位。

  • rtl情况下会自动翻转 r(right)与 l(left), 例如 rtl状态下tl bl与 非rtl状态下tr br等效下面的例子演示了如何将弹层定位到页面的右上角:

  1. <Overlay visible align="tr tr"><span>123</span></Overlay>

Popup

Popup 是对 Overlay 的封装,它接收某个节点作为触发节点,弹出一个浮层,这个浮层默认情况下使用这个节点作为定位的参照对象。

API

Overlay

参数说明类型默认值
children弹层内容any-
visible是否显示弹层Booleanfalse
onRequestClose弹层请求关闭时触发事件的回调函数签名:Function(type: String, e: Object) => void参数:type: {String} 弹层关闭的来源e: {Object} DOM 事件Functionfunc.noop
target弹层定位的参照元素anyPosition.VIEWPORT
align弹层相对于参照元素的定位, 详见开发指南的定位部分String/Boolean'tl bl'
offset弹层相对于trigger的定位的微调, 接收数组hoz, ver, 表示弹层在 left / top 上的增量e.g. 100, 100 表示往右(RTL 模式下是往左) 、下分布偏移100pxArray0, 0
container渲染组件的容器,如果是函数需要返回 ref,如果是字符串则是该 DOM 的 id,也可以直接传入 DOM 节点any-
hasMask是否显示遮罩Booleanfalse
canCloseByEsc是否支持 esc 按键关闭弹层Booleantrue
canCloseByOutSideClick点击弹层外的区域是否关闭弹层,不显示遮罩时生效Booleantrue
canCloseByMask点击遮罩区域是否关闭弹层,显示遮罩时生效Booleantrue
beforeOpen弹层打开前触发事件的回调函数签名:Function() => voidFunctionfunc.noop
onOpen弹层打开时触发事件的回调函数签名:Function() => voidFunctionfunc.noop
afterOpen弹层打开后触发事件的回调函数, 如果有动画,则在动画结束后触发签名:Function() => voidFunctionfunc.noop
beforeClose弹层关闭前触发事件的回调函数签名:Function() => voidFunctionfunc.noop
onClose弹层关闭时触发事件的回调函数签名:Function() => voidFunctionfunc.noop
afterClose弹层关闭后触发事件的回调函数, 如果有动画,则在动画结束后触发签名:Function() => voidFunctionfunc.noop
beforePosition弹层定位完成前触发的事件签名:Function() => voidFunctionfunc.noop
onPosition弹层定位完成时触发的事件签名:Function(config: Object, node: Object) => void参数:config: {Object} 定位的参数config.align: {Array} 对齐方式,如 'cc', 'cc'(如果开启 needAdjust,可能和预先设置的 align 不同)config.top: {Number} 距离视口顶部距离config.left: {Number} 距离视口左侧距离node: {Object} 定位参照的容器节点Functionfunc.noop
shouldUpdatePosition是否在每次弹层重新渲染后强制更新定位信息,一般用于弹层内容区域大小发生变化时,仍需保持原来的定位方式Booleanfalse
autoFocus弹层打开时是否让其中的元素自动获取焦点Booleanfalse
needAdjust当弹层由于页面滚动等情况不在可视区域时,是否自动调整定位以出现在可视区域Booleantrue
disableScroll是否禁用页面滚动Booleanfalse
cache隐藏时是否保留子节点Booleanfalse
safeNode安全节点,当点击 document 的时候,如果包含该节点则不会关闭弹层,如果是函数需要返回 ref,如果是字符串则是该 DOM 的 id,也可以直接传入 DOM 节点,或者以上值组成的数组any-
wrapperClassName弹层的根节点的样式类String-
wrapperStyle弹层的根节点的内联样式Object-
animation配置动画的播放方式,支持 { in: 'enter-class', out: 'leave-class' } 的对象参数,如果设置为 false,则不播放动画。 请参考 Animate 组件的文档获取可用的动画名Object/Boolean{ in: 'expandInDown', out: 'expandOutUp' }

Overlay.Popup

继承 Overlay 的 API,除非特别说明

参数说明类型默认值
children弹层内容ReactNode-
trigger触发弹层显示或隐藏的元素ReactElement-
triggerType触发弹层显示或隐藏的操作类型,可以是 'click','hover','focus',或者它们组成的数组,如 'hover', 'focus'String/Array'hover'
triggerClickKeycode当 triggerType 为 click 时才生效,可自定义触发弹层显示的键盘码Number/ArrayKEYCODE.SPACE, KEYCODE.ENTER
visible弹层当前是否显示Boolean-
defaultVisible弹层默认是否显示Booleanfalse
onVisibleChange弹层显示或隐藏时触发的回调函数签名:Function(visible: Boolean, type: String, e: Object) => void参数:visible: {Boolean} 弹层是否显示type: {String} 触发弹层显示或隐藏的来源 fromTrigger 表示由trigger的点击触发; docClick 表示由document的点击触发e: {Object} DOM事件Functionfunc.noop
disabled设置此属性,弹层无法显示或隐藏Booleanfalse
delay弹层显示或隐藏的延时时间(以毫秒为单位),在 triggerType 被设置为 hover 时生效Number200
canCloseByTriggertrigger 是否可以关闭弹层Booleantrue
target弹层定位的参照元素anytarget 属性,即触发元素
followTrigger是否跟随trigger滚动Booleanfalse

ARIA and KeyBoard

说明: 此组件需要结合其他组件使用,会有提示。参考上文无障碍

代码示例

基本

弹出一个弹层。

Overlay 弹层 - 图1

查看源码在线预览

  1. import { Overlay } from '@alifd/next';
  2. class Demo extends React.Component {
  3. constructor(props) {
  4. super(props);
  5. this.state = {
  6. visible: false
  7. };
  8. }
  9. onClick = () => {
  10. this.setState({
  11. visible: !this.state.visible
  12. });
  13. }
  14. onClose = () => {
  15. this.setState({
  16. visible: false
  17. });
  18. }
  19. render() {
  20. return (
  21. <div>
  22. <button onClick={this.onClick} ref={ref => {
  23. this.btn = ref;
  24. }}>
  25. Toggle visible
  26. </button>
  27. <Overlay visible={this.state.visible}
  28. target={() => this.btn}
  29. safeNode={() => this.btn}
  30. onRequestClose={this.onClose}>
  31. <span className="overlay-demo">
  32. Hello World From Overlay!
  33. </span>
  34. </Overlay>
  35. </div>
  36. );
  37. }
  38. }
  39. ReactDOM.render(<Demo />, mountNode);
  1. .overlay-demo {
  2. width: 300px;
  3. height: 100px;
  4. padding: 10px;
  5. border: 1px solid #999999;
  6. background: #FFFFFF;
  7. box-shadow: 2px 2px 20px rgba(0,0,0,0.15);
  8. }

遮罩

带有遮罩的弹层。

Overlay 弹层 - 图2

查看源码在线预览

  1. import { Overlay } from '@alifd/next';
  2. class Demo extends React.Component {
  3. constructor(props) {
  4. super(props);
  5. this.state = {
  6. visible: false
  7. };
  8. }
  9. onClick = () => {
  10. this.setState({
  11. visible: true
  12. });
  13. }
  14. onClose = () => {
  15. this.setState({
  16. visible: false
  17. });
  18. }
  19. render() {
  20. return (
  21. <div>
  22. <button onClick={this.onClick} ref={ref => {
  23. this.btn = ref;
  24. }}>
  25. Open
  26. </button>
  27. <Overlay visible={this.state.visible}
  28. safeNode={() => this.btn}
  29. align="cc cc"
  30. hasMask
  31. disableScroll
  32. onRequestClose={this.onClose}>
  33. <span className="overlay-demo">
  34. Hello World From Overlay!
  35. </span>
  36. </Overlay>
  37. </div>
  38. );
  39. }
  40. }
  41. ReactDOM.render(<Demo />, mountNode);
  1. .overlay-demo {
  2. width: 300px;
  3. height: 100px;
  4. padding: 10px;
  5. border: 1px solid #999999;
  6. background: #FFFFFF;
  7. box-shadow: 2px 2px 20px rgba(0,0,0,0.15);
  8. }

触发的弹层

使用 Popup 弹出一个弹层。

Overlay 弹层 - 图3

查看源码在线预览

  1. import { Overlay } from '@alifd/next';
  2. const { Popup } = Overlay;
  3. ReactDOM.render(
  4. <div>
  5. <Popup trigger={<button>Open</button>} triggerType="click">
  6. <span className="overlay-demo">
  7. Hello World From Popup!
  8. </span>
  9. </Popup>
  10. <br />
  11. <Popup trigger={<button>Use Down Arrow to open</button>} triggerType="click" triggerClickKeycode={40}>
  12. <span className="overlay-demo">
  13. Hello World From Popup!
  14. </span>
  15. </Popup>
  16. </div>
  17. , mountNode);
  1. .overlay-demo {
  2. width: 300px;
  3. height: 100px;
  4. padding: 10px;
  5. border: 1px solid #999999;
  6. background: #FFFFFF;
  7. box-shadow: 2px 2px 20px rgba(0,0,0,0.15);
  8. }

触发的弹层受控显示隐藏

展示了 Popup 受控显示隐藏的用法。

Overlay 弹层 - 图4

查看源码在线预览

  1. import { Overlay } from '@alifd/next';
  2. const { Popup } = Overlay;
  3. class Demo extends React.Component {
  4. constructor(props) {
  5. super(props);
  6. this.state = {
  7. visible: false
  8. };
  9. }
  10. onVisibleChange = visible => {
  11. this.setState({
  12. visible
  13. });
  14. }
  15. onGroupVisibleChange = groupVisible => {
  16. this.setState({
  17. groupVisible
  18. });
  19. }
  20. render() {
  21. return (
  22. <div>
  23. <div>
  24. <Popup trigger={<button>Open</button>}
  25. triggerType="click"
  26. visible={this.state.visible}
  27. onVisibleChange={this.onVisibleChange}>
  28. <span className="overlay-demo">
  29. Hello World From Popup!
  30. </span>
  31. </Popup>
  32. </div>
  33. <br />
  34. <div>
  35. <Popup trigger={<button style={{"margin-right": "50px"}} ref={ref => {this.btn1 = ref;}}>Paired Popup 1</button>}
  36. triggerType="click"
  37. visible={this.state.groupVisible}
  38. safeNode={[() => this.btn2, () => this.overlay2]}
  39. onVisibleChange={this.onGroupVisibleChange}>
  40. <span className="overlay-demo" ref={ref => {this.overlay1 = ref;}}>
  41. Hello World From Popup!
  42. </span>
  43. </Popup>
  44. <Popup trigger={<button ref={ref => {this.btn2 = ref;}}>Paired Popup 2</button>}
  45. triggerType="click"
  46. visible={this.state.groupVisible}
  47. safeNode={[() => this.btn1, () => this.overlay1]}
  48. onVisibleChange={this.onGroupVisibleChange}>
  49. <span className="overlay-demo" ref={ref => {this.overlay2 = ref;}}>
  50. Hello World From Popup!
  51. </span>
  52. </Popup>
  53. </div>
  54. </div>
  55. );
  56. }
  57. }
  58. ReactDOM.render(<Demo />, mountNode);
  1. .overlay-demo {
  2. width: 300px;
  3. height: 100px;
  4. padding: 10px;
  5. border: 1px solid #999999;
  6. background: #FFFFFF;
  7. box-shadow: 2px 2px 20px rgba(0,0,0,0.15);
  8. }

弹层嵌套

有弹层嵌套需求时,请使用 container 属性将第二个弹层渲染到第一个弹层内部。

Overlay 弹层 - 图5

查看源码在线预览

  1. import { Overlay } from '@alifd/next';
  2. const { Popup } = Overlay;
  3. ReactDOM.render(
  4. <Popup trigger={<button>Open first overlay</button>}
  5. triggerType="click">
  6. <div className="overlay-demo">
  7. <Popup trigger={<button>Open second overlay</button>}
  8. triggerType="click"
  9. container={trigger => trigger.parentNode}>
  10. <div className="overlay-demo">
  11. <p>Hello World From Second Overlay!</p>
  12. </div>
  13. </Popup>
  14. <p>Hello World From First Overlay!</p>
  15. </div>
  16. </Popup>
  17. , mountNode);
  1. .overlay-demo {
  2. width: 300px;
  3. height: 100px;
  4. padding: 10px;
  5. border: 1px solid #999999;
  6. background: #FFFFFF;
  7. box-shadow: 2px 2px 20px rgba(0,0,0,0.15);
  8. }

弹层跟随滚动

弹层默认参照 document.body 绝对定位,如果弹层显示隐藏的触发元素所在容器(一般为父节点)有滚动条,那么当容器滚动时,会发生触发元素与弹层相分离的情况,解决的办法是将弹层渲染到触发元素所在的容器中。(触发元素所在的容器,必须设置 position 样式,以完成弹层的绝对定位。)

Overlay 弹层 - 图6

查看源码在线预览

  1. import { Overlay } from '@alifd/next';
  2. const { Popup } = Overlay;
  3. ReactDOM.render(
  4. <div className="scroll-container">
  5. <Popup trigger={<button>Open</button>}
  6. triggerType="click"
  7. container={trigger => trigger.parentNode}>
  8. <div className="overlay-demo">
  9. Hello World From Popup!
  10. </div>
  11. </Popup>
  12. <div style={{ height: '300px' }} />
  13. </div>
  14. , mountNode);
  1. .overlay-demo {
  2. width: 300px;
  3. height: 100px;
  4. padding: 10px;
  5. border: 1px solid #999999;
  6. background: #FFFFFF;
  7. box-shadow: 2px 2px 20px rgba(0,0,0,0.15);
  8. }
  9. .scroll-container {
  10. position: relative;
  11. height: 150px;
  12. padding: 10px;
  13. border: 1px solid #999999;
  14. overflow: auto;
  15. }

对齐

可以自定义对齐方式

Overlay 弹层 - 图7

查看源码在线预览

  1. import { Overlay } from '@alifd/next';
  2. const { Popup } = Overlay;
  3. ReactDOM.render(
  4. <div >
  5. <div id="container1" className="overlay-container">
  6. normal example
  7. <Overlay target="container1" visible align="tr tr"><span>123</span></Overlay>
  8. <Overlay target="container1" visible align="cc cr"><span>123</span></Overlay>
  9. <Overlay target="container1" visible align="bc bc"><span>123</span></Overlay>
  10. </div>
  11. <br /><br /><br /><br />
  12. <div id="container2" className="overlay-container" dir="rtl">
  13. dir=rtl example
  14. <Overlay target="container2" rtl visible align="tr tr"><span>123</span></Overlay>
  15. <Overlay target="container2" rtl visible align="cc cr"><span>123</span></Overlay>
  16. <Overlay target="container2" rtl visible align="bc bc"><span>123</span></Overlay>
  17. </div>
  18. </div>
  19. , mountNode);
  1. .overlay-container {
  2. position: relative;
  3. height: 150px;
  4. margin: 50px;
  5. border: 1px solid #999;
  6. overflow: auto;
  7. text-align: center;
  8. color: red;
  9. }

相关区块

Overlay 弹层 - 图8

暂无相关区块