index.vue 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. <template>
  2. <Teleport to="body" :disabled="!appendToBody">
  3. <transition
  4. name="fade"
  5. @after-enter="afterEnter"
  6. @after-leave="afterLeave"
  7. >
  8. <div class="m-dialog" v-show="modelValue" @click.self="handleWrapperClick">
  9. <div
  10. ref="dialogRef"
  11. role="dialog"
  12. class="m-dialog__contentbox"
  13. :class="[
  14. {'m-dialog--center': center },
  15. {'is-draggable': draggable },
  16. customClass
  17. ]"
  18. :style="contentboxStyle"
  19. >
  20. <div class="m-dialog__header" ref="headerRef">
  21. <slot name="header">
  22. <span class="m-dialog__title">{{ title }}</span>
  23. </slot>
  24. <i class="iconfont icon-close" @click="handleClose" v-if="showClose"></i>
  25. </div>
  26. <div class="m-dialog__body">
  27. <slot></slot>
  28. </div>
  29. <div class="m-dialog__footer">
  30. <slot name="footer"></slot>
  31. </div>
  32. </div>
  33. </div>
  34. </transition>
  35. </Teleport>
  36. </template>
  37. <script>
  38. export default {
  39. name: "mDialog"
  40. };
  41. </script>
  42. <script setup>
  43. import { computed, ref, watch } from 'vue-demi';
  44. import { useDraggable } from '~/hooks/use-draggable';
  45. const emit = defineEmits(['update:modelValue','close','open','opened','closed'])
  46. const props = defineProps({
  47. modelValue:Boolean,
  48. title: {
  49. type: String,
  50. default: ''
  51. },
  52. width: String,
  53. top: {
  54. type: String,
  55. default: '15vh'
  56. },
  57. center: {
  58. type: Boolean,
  59. default: false
  60. },
  61. draggable: {
  62. type: Boolean,
  63. default: false
  64. },
  65. appendToBody: {
  66. type: Boolean,
  67. default: false
  68. },
  69. closeOnClickModal: {
  70. type: Boolean,
  71. default: true
  72. },
  73. customClass: {
  74. type: String,
  75. default: ''
  76. },
  77. showClose: {
  78. type: Boolean,
  79. default: true
  80. }
  81. })
  82. const dialogRef = ref(null)
  83. const headerRef = ref(null)
  84. const draggable = computed(() => props.draggable)
  85. useDraggable(dialogRef, headerRef, draggable)
  86. const contentboxStyle = computed(() => {
  87. return {
  88. marginTop: props.top,
  89. width: props.width
  90. }
  91. })
  92. watch(() =>props.modelValue,(val) => {
  93. if(val) {
  94. emit('open')
  95. }
  96. })
  97. const handleClose = () =>{
  98. emit('close')
  99. emit('update:modelValue',false)
  100. }
  101. const handleWrapperClick = () => {
  102. if (!props.closeOnClickModal) return;
  103. handleClose()
  104. }
  105. const afterEnter = () => {
  106. emit('opened')
  107. }
  108. const afterLeave = () => {
  109. emit('closed')
  110. }
  111. </script>
  112. <style lang="scss" scoped>
  113. @import '../../styles/components/dialog.scss';
  114. .fade-enter-active, .fade-leave-active {
  115. transition: opacity .2s ease;
  116. }
  117. .fade-enter-from, .fade-leave-to {
  118. opacity: 0;
  119. }
  120. </style>