Skip to content

Modal对话框

用于需要用户响应的操作或信息展示

打开方式

支持两种打开方式 使用 trigger插槽ModalRef

使用 trigger插槽 时点击即可自动打开抽屉

使用 ModalRef 时需自行调用 open 方法

点击trigger插槽打开
使用 open 方法打开
vue
<template>
  <div class="flex flex-col gap-y-4">
    <Modal>
      <template #trigger>
        <div class="btn">点击trigger插槽打开</div>
      </template>
      <template #body>
        <p>这是点击trigger插槽打开的对话框</p>
      </template>
    </Modal>

    <div class="btn" @click="handleOpenModal">使用 open 方法打开</div>

    <Modal ref="drawerRef">
      <template #body>
        <p>这是使用open方法打开的对话框</p>
      </template>
    </Modal>
  </div>
</template>

<script setup lang="ts">
import { Modal } from 'li-daisy'
import type { ModalRef } from 'li-daisy'
import { ref } from 'vue'

const drawerRef = ref<ModalRef>()
const handleOpenModal = () => {
  drawerRef.value?.open()
}
</script>

打开方向

direction可选值有 ltr rtl middle ttb btt,默认值为 无打开方向居中显示

上↓下
左→右
中间
左←右
上↑下
vue
<template>
  <div class="grid gap-4 grid-cols-3 min-w-sm">
    <div></div>

    <Modal direction="ttb">
      <template #body>
        <h3 class="font-bold text-lg">从上到下 (ttb)</h3>
        <p class="py-4">This is the modal content.</p>
      </template>
      <template #trigger>
        <div class="btn">上↓下</div>
      </template>
    </Modal>

    <div></div>

    <Modal direction="ltr">
      <template #body>
        <h3 class="font-bold text-lg">从左到右 (ltr)</h3>
        <p class="py-4">This is the modal content.</p>
      </template>
      <template #trigger>
        <div class="btn">左→右</div>
      </template>
    </Modal>

    <Modal direction="middle">
      <template #body>
        <h3 class="font-bold text-lg">中间 (middle)</h3>
        <p class="py-4">This is the modal content.</p>
      </template>
      <template #trigger>
        <div class="btn">中间</div>
      </template>
    </Modal>

    <Modal direction="rtl">
      <template #body>
        <h3 class="font-bold text-lg">从右到左 (rtl)</h3>
        <p class="py-4">This is the modal content.</p>
      </template>
      <template #trigger>
        <div class="btn">左←右</div>
      </template>
    </Modal>

    <div></div>

    <Modal direction="btt">
      <template #body>
        <h3 class="font-bold text-lg">从下到上 (btt)</h3>
        <p class="py-4">This is the modal content.</p>
      </template>
      <template #trigger>
        <div class="btn">上↑下</div>
      </template>
    </Modal>
  </div>
</template>

<script setup lang="ts">
import { Modal } from 'li-daisy'
</script>

设置大小/支持响应式

注意

该本质是绑定到Modal上的动态css,所有使用的要尤其小心,避免造成副作用

通过size设置宽度大小,支持 Tailwind CSS 的任意宽度值(包括响应式写法)

不设置方向时,即居中显示时:modal默认设置了 max-width512px

当direction为 ttbbtt 要设置对应的 height max-height

当direction为 ltrrtl 要设置对应的 width max-width

自行定义的时候要修改 width max-widthheigth max-heigth

vue
<template>
  <div>
    <Modal
      ref="modalRef"
      direction="ltr"
      size="w-[80vw] min-w-[200px] md:w-[60vw] md:max-w-[400px] lg:w-[50vw] lg:max-w-[600px]"
    >
      <template #body>
        <h3 class="font-bold text-lg">动态大小</h3>
        <p class="py-4">调整屏幕大小,观察modal宽度</p>
      </template>
    </Modal>

    <button class="btn" @click="handleOpenModal">打开动态modal</button>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'
import { Modal, type ModalRef } from 'li-daisy'

const modalRef = ref<ModalRef>()

const handleOpenModal = () => {
  modalRef.value?.open()
}
</script>

显示关闭图标

通过设置 show-close-icon 来控制是否显示图标,默认值为 true

vue
<template>
  <div class="flex w-full justify-between gap-x-5">
    <Modal ref="modalRef1" show-close-icon>
      <template #body>
        <h3 class="font-bold text-lg">该modal有关闭图标</h3>
        <p class="py-4">该modal有关闭图标</p>
      </template>
    </Modal>

    <button class="btn" @click="handleOpenModal1">该modal有关闭图标</button>

    <Modal ref="modalRef2" :show-close-icon="false">
      <template #body>
        <h3 class="font-bold text-lg">该modal无关闭图标</h3>
        <p class="py-4">该modal无关闭图标</p>
      </template>
    </Modal>

    <button class="btn" @click="handleOpenModal2">该modal无关闭图标</button>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'
import { Modal, type ModalRef } from 'li-daisy'

const modalRef1 = ref<ModalRef>()

const handleOpenModal1 = () => {
  modalRef1.value?.open()
}

const modalRef2 = ref<ModalRef>()

const handleOpenModal2 = () => {
  modalRef2.value?.open()
}
</script>

点击蒙层关闭

通过设置 close-on-click-modal 来控制点击图层是否关闭,默认值为 true

IMPORTANT

当设置了 close-on-click-modal 为true时,关闭图标不再受控制,必然显示

vue
<template>
  <div class="flex w-full justify-between gap-x-5">
    <Modal ref="modalRef1" :close-on-click-modal="true">
      <template #body>
        <h3 class="font-bold text-lg">当前点击蒙层可关闭抽屉</h3>
        <p class="py-4">当前点击蒙层可关闭modal</p>
      </template>
    </Modal>

    <button class="btn" @click="handleOpenModal1">点击蒙层可关闭</button>

    <Modal ref="modalRef2" :close-on-click-modal="false">
      <template #body>
        <h3 class="font-bold text-lg">当前点击蒙层不可关闭抽屉</h3>
        <p class="py-4">当前点击蒙层不可关闭抽屉</p>
      </template>
    </Modal>

    <button class="btn" @click="handleOpenModal2">点击蒙层不可关闭</button>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'
import { Modal, type ModalRef } from 'li-daisy'

const modalRef1 = ref<ModalRef>()

const handleOpenModal1 = () => {
  modalRef1.value?.open()
}

const modalRef2 = ref<ModalRef>()

const handleOpenModal2 = () => {
  modalRef2.value?.open()
}
</script>

emit

vue
<template>
  <div>
    <Modal ref="modalRef" @open="handleOpen" @close="handleClose">
      <template #body>
        <h3 class="font-bold text-lg">emit例子</h3>
        <p class="py-4">emit例子</p>
      </template>
    </Modal>

    <button class="btn" @click="handleOpenModal">emit例子</button>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'
import { Message, Modal, type ModalRef } from 'li-daisy'

const modalRef = ref<ModalRef>()

const handleOpenModal = () => {
  modalRef.value?.open()
}

const handleOpen = () => {
  Message.success('modal被打开了')
}

const handleClose = () => {
  Message.warning('modal被关闭了')
}
</script>

关闭时注销组件

destroy-on-close 属性决定关闭 modal 时是否卸载组件,默认为 false

需要每次打开弹窗都初始化内容时,建议设置 destroy-on-closetrue

需要保留弹窗内表单、计数器等状态时,建议保持默认(false

效果类似于 keep-alive

vue
<template>
  <div class="flex gap-8">
    <!-- 会卸载内容的弹窗 -->
    <div>
      <Modal ref="modalRef1" :destroy-on-close="true">
        <template #body>
          <h3 class="font-bold text-lg">关闭时卸载组件</h3>
          <p class="py-4">弹窗关闭后,内部内容会被卸载,重新打开会重新挂载。</p>
          <Count />
        </template>
      </Modal>
      <button class="btn" @click="handleOpenModal1">打开弹窗(卸载内容)</button>
    </div>

    <!-- 不会卸载内容的弹窗 -->
    <div>
      <Modal ref="modalRef2">
        <template #body>
          <h3 class="font-bold text-lg">关闭时不卸载组件</h3>
          <p class="py-4">弹窗关闭后,内部内容不会被卸载,重新打开会保留上次状态。</p>
          <Count />
        </template>
      </Modal>
      <button class="btn" @click="handleOpenModal2">打开弹窗(保留内容)</button>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'
import { Modal, type ModalRef } from 'li-daisy'
import Count from '../demo/Count.vue'

const modalRef1 = ref<ModalRef>()
const modalRef2 = ref<ModalRef>()

const handleOpenModal1 = () => {
  modalRef1.value?.open()
}
const handleOpenModal2 = () => {
  modalRef2.value?.open()
}
</script>

自定义header

可使用 header 插槽自定义抽屉头部,并且该插槽暴露一个 close 方法用于关闭抽屉

IMPORTANT

由于自定义了header,由此此时 show-close-icon 将不再有实际作用

同理,若将 close-on-click-modal 设置为 false,请务必确保留有关闭的按钮或图标等,以此确保用户体验

vue
<template>
  <div>
    <Modal ref="modalRef" :close-on-click-modal="false">
      <template #header="{ close }">
        <div class="flex w-full justify-between border-b border-b-base-300 p-3">
          <h2 class="font-bold">自定义header</h2>
          <div class="btn btn-circle btn-xs text-lg" @click="close">×</div>
        </div>
      </template>
      <template #body>
        <p>这是body</p>
      </template>
    </Modal>

    <button class="btn" @click="handleOpenModal">自定义header</button>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'
import { Modal, type ModalRef } from 'li-daisy'

const modalRef = ref<ModalRef>()

const handleOpenModal = () => {
  modalRef.value?.open()
}
</script>

去除body插槽的padding

通过设置 no-body-padding 属性,可以去除 Modal 内容区域(body 插槽)的默认内边距,方便你自定义内容样式

默认情况下 body 区域会有适当的 padding,设置为 true 后将完全移除,内容将紧贴容器边缘

API

Attributes

属性值说明类型默认值
size抽屉大小string'w-11/12 max-w-[512px]'
show-close-icon是否显示关闭图标booleantrue
close-on-click-modal点击蒙层是否关闭抽屉booleantrue
destroy-on-close关闭组件时是否卸载组件booleanfalse
no-body-padding是否去除 body 区域的默认 paddingbooleanfalse

Slots

插槽名说明
trigger打开对话框触发器
header对话框头部
body对话框内容

Event

名称说明类型
open打开modal回调() => void
close关闭modal回调() => void

Expose

方法名说明类型
open控制抽屉打开() => void
close控制抽屉关闭() => void