l-overlay.uvue 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. <template>
  2. <view v-if="inited"
  3. class="l-overlay"
  4. ref="overlayRef"
  5. :class="[lClass, classes]"
  6. :style="[styles, lStyle]"
  7. @click.stop="onClick"
  8. @touchmove.stop="noop"
  9. @transitionend="finished"
  10. :aria-role="ariaRole"
  11. :aria-label="ariaLabel">
  12. <slot></slot>
  13. </view>
  14. </template>
  15. <script lang="uts" setup>
  16. /**
  17. * Overlay 遮罩层组件
  18. * @description 用于创建模态遮罩层,通常配合弹窗、对话框等组件使用
  19. * <br>插件类型:LOverlayComponentPublicInstance
  20. * @tutorial https://ext.dcloud.net.cn/plugin?name=lime-overlay
  21. *
  22. * @property {string} ariaLabel 无障碍访问标签(需语义化描述作用)
  23. * @property {string} ariaRole ARIA角色属性(默认:'presentation')
  24. * @property {string} lClass 自定义类名(会覆盖默认样式)
  25. * @property {string} bgColor 背景颜色(默认:'rgba(0, 0, 0, 0.7)')
  26. * @property {string} lStyle 自定义样式(最高优先级,支持CSS字符串)
  27. * @property {number} duration 背景过渡动画时长(单位:ms,默认:300)
  28. * @property {boolean} preventScrollThrough 阻止滚动穿透(默认:true)
  29. * @property {boolean} visible 是否显示遮罩层(支持v-model)
  30. * @property {number} zIndex 层级(默认:1000)
  31. * @event {Function} click 点击遮罩层时触发(常用于关闭操作)
  32. * @event {Function} before-enter
  33. * @event {Function} enter
  34. * @event {Function} after-enter
  35. * @event {Function} before-leave
  36. * @event {Function} leave
  37. * @event {Function} after-leave
  38. */
  39. import { useTransition, type UseTransitionOptions, type TransitionEmitStatus } from '@/uni_modules/lime-transition';
  40. import { OverlayProps } from './type';
  41. // defineOptions({
  42. // name:'l-overlay'
  43. // })
  44. const props = withDefaults(defineProps<OverlayProps>(), {
  45. ariaLabel: '关闭',
  46. ariaRole: 'button',
  47. preventScrollThrough: true,
  48. zIndex: 998,
  49. visible: false,
  50. duration: 300,
  51. })
  52. const emit = defineEmits(['click', 'before-enter', 'enter', 'after-enter', 'before-leave', 'leave', 'after-leave'])
  53. const {inited, display, classes, finished} = useTransition({
  54. defaultName: 'fade',
  55. appear: props.visible,
  56. emits: (name:TransitionEmitStatus) => { emit(name) },
  57. visible: (): boolean => props.visible,
  58. duration: props.duration,
  59. } as UseTransitionOptions)
  60. const styles = computed<Map<string,any>>(():Map<string,any> => {
  61. const style = new Map<string,any>();
  62. if (props.bgColor != null) {
  63. style.set("background-color", props.bgColor!)
  64. }
  65. if (props.zIndex > 0) {
  66. style.set("z-index", props.zIndex)
  67. }
  68. // #ifndef APP || WEB
  69. style.set('transition-duration', props.duration + 'ms')
  70. if (!display.value) {
  71. style.set("display", "none")
  72. }
  73. // #endif
  74. return style
  75. })
  76. const noop = () => {}
  77. const onClick = (event: UniPointerEvent) =>{
  78. // event.stopPropagation()
  79. emit('click', !props.visible)
  80. }
  81. // #ifdef APP || WEB
  82. const overlayRef = ref<UniElement|null>(null)
  83. watchEffect(()=>{
  84. overlayRef.value?.style.setProperty('transition-duration', `${props.duration}ms`)
  85. if(!display.value){
  86. overlayRef.value?.style.setProperty('display', "none")
  87. } else {
  88. overlayRef.value?.style.setProperty('display', "flex")
  89. }
  90. })
  91. // #endif
  92. </script>
  93. <style lang="scss">
  94. @import './index';
  95. </style>