Skip to content

对话框

通过html原生<dialog>标签封装的对话框组件。参考

dialog有最顶层的渲染能力(top-layer),其他元素即使设置了z-index也不能在dialog上显示。比如全局的Message消息 它也只能在dialog下面渲染,很多第三方组件有挂载到指定元素的功能,这时候最好把他挂载到dialog上,比如日期选择器。

标题文字

x

样式可以完全自定义的对话框组件

按esc键也可以关闭

在里面提交表单的时候会自动关闭对话框 点击这里查看原因

dialog::backdrop 设置遮罩层颜色

代码
vue
<script setup>
import {ref, watch} from 'vue'

const props = defineProps({
  modelValue: {
    type: Boolean,
    default: false
  }
})
const emit = defineEmits(['update:modelValue'])

const dialog = ref(null)
watch(() => props.modelValue, (value) => {
  if (value) {
    return dialog.value.showModal()
  }
  dialog.value.close()
})

const closeDialog = () => {
  dialog.value.close()
  emit('update:modelValue', false)
}
// 点击对话框外面的区域,关闭对话框
const onClick = (e) => {
  const dialogDimensions = dialog.value.getBoundingClientRect()
  if (
      e.clientX < dialogDimensions.left ||
      e.clientX > dialogDimensions.right ||
      e.clientY < dialogDimensions.top ||
      e.clientY > dialogDimensions.bottom
  ) {
    closeDialog()
  }
}
</script>

<template>
  <dialog ref="dialog" class="my-dialog" @click="onClick" @cancel="closeDialog">
    <slot>
      <slot name="title">
        <div class="my-dialog-title">
          <p class="my-dialog-title_text"><slot name="title-text">标题文字</slot></p>
          <div class="my-dialog-close" @click.stop="closeDialog">
            x
          </div>
        </div>
      </slot>

      <slot name="body">
        内容区
      </slot>
    </slot>
  </dialog>
</template>

<style scoped lang="less">
.my-dialog {
  border: 0;
  padding: 20px;
  border-radius: 4px;
  // 如果不设置这个属性,元素超出dialog范围会被隐藏
  overflow: visible;

  .my-dialog-title {
    display: flex;
    gap: 20px;
    align-items: center;
    justify-content: space-between;
    padding-bottom: 20px;

    .my-dialog-title_text {
      font-size: 16px;
      font-weight: 600;
    }

    .my-dialog-close:hover {
      cursor: pointer;
      background-color: #f3f3f3;
    }
  }
}
</style>