|
|
@@ -1,54 +1,83 @@
|
|
|
<!-- 基础模态框组件 -->
|
|
|
<template>
|
|
|
- <app-mask :class="['app-modal', direction]" :show="show" :delay="delay" @mask="emit('mask')">
|
|
|
- <div :class="['app-modal__container', transitionClass]" :style="transitionStyles">
|
|
|
- <div class="app-modal__header">
|
|
|
- <slot name="header"></slot>
|
|
|
- </div>
|
|
|
- <div class="app-modal__body">
|
|
|
- <slot></slot>
|
|
|
- </div>
|
|
|
- <div class="app-modal__footer">
|
|
|
- <slot name="footer"></slot>
|
|
|
- </div>
|
|
|
+ <div class="app-modal" :style="modalStyles" v-show="visible">
|
|
|
+ <div :class="['app-modal__mask', transitionClass]" :style="transitionStyles"></div>
|
|
|
+ <div :class="['app-modal__wrapper', direction]" @click.self="onMask">
|
|
|
+ <div :class="['app-modal__container', transitionClass]" :style="transitionStyles">
|
|
|
+ <div class="app-modal__header">
|
|
|
+ <slot name="header"></slot>
|
|
|
+ </div>
|
|
|
+ <div class="app-modal__body">
|
|
|
+ <slot></slot>
|
|
|
+ </div>
|
|
|
+ <div class="app-modal__footer">
|
|
|
+ <slot name="footer"></slot>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
- </app-mask>
|
|
|
</template>
|
|
|
|
|
|
<script lang="ts" setup>
|
|
|
-import { watch, PropType } from 'vue'
|
|
|
-import { useMask } from '../mask'
|
|
|
-import AppMask from '../mask/index.vue'
|
|
|
+import { computed, watch, PropType } from 'vue';
|
|
|
+import { useModal } from './index'
|
|
|
|
|
|
const emit = defineEmits(['mask', 'opened', 'closed']);
|
|
|
|
|
|
const props = defineProps({
|
|
|
- show: {
|
|
|
- type: Boolean,
|
|
|
- default: false,
|
|
|
- },
|
|
|
- // 窗口动画时间
|
|
|
- delay: {
|
|
|
- type: Number,
|
|
|
- default: 200,
|
|
|
- },
|
|
|
- // 窗口弹出方向
|
|
|
- direction: {
|
|
|
- type: String as PropType<'full' | 'center' | 'left' | 'right' | 'top' | 'bottom' | 'left-top' | 'left-bottom' | 'right-top' | 'right-bottom'>,
|
|
|
- default: 'center',
|
|
|
- },
|
|
|
+ show: {
|
|
|
+ type: Boolean,
|
|
|
+ default: false,
|
|
|
+ },
|
|
|
+ // 是否可以点击遮罩关闭窗口
|
|
|
+ closeOnClickMask: {
|
|
|
+ type: Boolean,
|
|
|
+ default: true,
|
|
|
+ },
|
|
|
+ // 绝对定位
|
|
|
+ fixed: {
|
|
|
+ type: Boolean,
|
|
|
+ default: true,
|
|
|
+ },
|
|
|
+ // 遮罩堆叠顺序
|
|
|
+ zIndex: {
|
|
|
+ type: Number,
|
|
|
+ default: 1000,
|
|
|
+ },
|
|
|
+ // 窗口动画时间
|
|
|
+ delay: {
|
|
|
+ type: Number,
|
|
|
+ default: 250,
|
|
|
+ },
|
|
|
+ // 窗口弹出方向
|
|
|
+ direction: {
|
|
|
+ type: String as PropType<'full' | 'center' | 'left' | 'right' | 'top' | 'bottom' | 'left-top' | 'left-bottom' | 'right-top' | 'right-bottom'>,
|
|
|
+ default: 'center',
|
|
|
+ },
|
|
|
})
|
|
|
|
|
|
-const { transitionClass, transitionStyles, transition } = useMask(props.show, props.delay);
|
|
|
+const { visible, transitionClass, transitionStyles, transition } = useModal(props.show, props.delay);
|
|
|
|
|
|
-watch(() => props.show, (isShow) => {
|
|
|
- transition(isShow, () => {
|
|
|
- if (isShow) {
|
|
|
- emit('opened');
|
|
|
- } else {
|
|
|
- emit('closed');
|
|
|
+const modalStyles = computed(() => ({
|
|
|
+ position: props.fixed ? 'fixed' : 'absolute',
|
|
|
+ zIndex: props.zIndex,
|
|
|
+}))
|
|
|
+
|
|
|
+// 点击遮罩事件
|
|
|
+const onMask = () => {
|
|
|
+ if (props.closeOnClickMask) {
|
|
|
+ emit('mask');
|
|
|
}
|
|
|
- })
|
|
|
+}
|
|
|
+
|
|
|
+watch(() => props.show, (isShow) => {
|
|
|
+ transition(isShow, () => {
|
|
|
+ if (isShow) {
|
|
|
+ emit('opened');
|
|
|
+ } else {
|
|
|
+ emit('closed');
|
|
|
+ }
|
|
|
+ })
|
|
|
})
|
|
|
</script>
|
|
|
|