Skip to content
On this page

模态框 Modal

对话框/弹窗,在浮层中显示,引导用户进行相关操作。

基础用法

<template>
  <div>
    <b-button type="primary" @click="visible = true">Open</b-button>
    <b-button type="primary" @click="confirm = true">Confirm</b-button>
    <b-modal v-model="visible" title="普通的模态框标题" :z-index="1000">
      <p>我是弹窗内容...</p>
      <p>我是弹窗内容...</p>
      <p>我是弹窗内容...</p>
      <template #footer>
        <span>
          <b-button @click="onClose">取 消</b-button>
          <b-button type="primary" @click="onOk">确 定</b-button>
        </span>
      </template>
    </b-modal>
    <b-modal v-model="confirm" width="420px" :show-close="false">
      <div class="p8">
        <div class="f-s-18" flex="cross:center">
          <b-icon name="info-circle" size="24" color="#fa8c16"></b-icon>
          <span class="ml-8">提示</span>
        </div>
        <div style="padding: 8px 0 8px 32px">确认注销登录吗?</div>
        <div class="t-right">
          <b-button @click="confirm = false">取消</b-button>
          <b-button type="primary" @click="confirm = false">确定</b-button>
        </div>
      </div>
    </b-modal>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'
import { Message } from 'bin-ui-design'

const visible = ref(false)
const confirm = ref(false)

function onOk() {
  visible.value = false
  Message('点击确定')
}

function onClose() {
  visible.value = false
  Message('点击取消')
}
</script>
<template>
  <div>
    <b-button type="primary" @click="visible = true">Open</b-button>
    <b-button type="primary" @click="confirm = true">Confirm</b-button>
    <b-modal v-model="visible" title="普通的模态框标题" :z-index="1000">
      <p>我是弹窗内容...</p>
      <p>我是弹窗内容...</p>
      <p>我是弹窗内容...</p>
      <template #footer>
        <span>
          <b-button @click="onClose">取 消</b-button>
          <b-button type="primary" @click="onOk">确 定</b-button>
        </span>
      </template>
    </b-modal>
    <b-modal v-model="confirm" width="420px" :show-close="false">
      <div class="p8">
        <div class="f-s-18" flex="cross:center">
          <b-icon name="info-circle" size="24" color="#fa8c16"></b-icon>
          <span class="ml-8">提示</span>
        </div>
        <div style="padding: 8px 0 8px 32px">确认注销登录吗?</div>
        <div class="t-right">
          <b-button @click="confirm = false">取消</b-button>
          <b-button type="primary" @click="confirm = false">确定</b-button>
        </div>
      </div>
    </b-modal>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'
import { Message } from 'bin-ui-design'

const visible = ref(false)
const confirm = ref(false)

function onOk() {
  visible.value = false
  Message('点击确定')
}

function onClose() {
  visible.value = false
  Message('点击取消')
}
</script>

自定义样式

Modal 组件提供了灵活的自定义样式 API 和 Slot,可以自由控制整个 Modal 的各个组成部分,比如页头、页脚、关闭按钮。

<template>
  <div>
    <b-button @click="modal1 = true">自定义页头页脚</b-button>
    <b-button @click="modal2 = true">不带标题栏和页脚</b-button>
    <b-button @click="modal3 = true">设置宽</b-button>
    <b-button @click="modal4 = true">距离顶部200px</b-button>
    <b-button @click="modal5 = true">body-style</b-button>

    <b-modal v-model="modal1">
      <template #title>
        <p style="color: #f60; text-align: center">
          <span>自定义页头</span>
        </p>
      </template>
      <p>我是弹窗内容...</p>
      <p>我是弹窗内容...</p>
      <p>我是弹窗内容...</p>
      <template #footer>
        <b-button type="danger">Delete</b-button>
      </template>
    </b-modal>

    <b-modal v-model="modal2">
      <p>我是弹窗内容...</p>
      <p>我是弹窗内容...</p>
      <p>我是弹窗内容...</p>
    </b-modal>

    <b-modal v-model="modal3" title="自定义宽度" width="300px">
      <p>
        自定义宽度,单位 px,默认 520px。 对话框的宽度是响应式的,当屏幕尺寸小于 768px
        时,宽度会变为自动auto。
      </p>
    </b-modal>

    <b-modal v-model="modal4" title="距离顶部" top="200px">
      <p>距离顶部200px</p>
    </b-modal>

    <b-modal v-model="modal5" title="body-style" :body-styles="{ padding: '20px' }">
      <p>我是弹窗内容...</p>
      <p>我是弹窗内容...</p>
      <p>我是弹窗内容...</p>
    </b-modal>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'

const modal1 = ref(false)
const modal2 = ref(false)
const modal3 = ref(false)
const modal4 = ref(false)
const modal5 = ref(false)
</script>
<template>
  <div>
    <b-button @click="modal1 = true">自定义页头页脚</b-button>
    <b-button @click="modal2 = true">不带标题栏和页脚</b-button>
    <b-button @click="modal3 = true">设置宽</b-button>
    <b-button @click="modal4 = true">距离顶部200px</b-button>
    <b-button @click="modal5 = true">body-style</b-button>

    <b-modal v-model="modal1">
      <template #title>
        <p style="color: #f60; text-align: center">
          <span>自定义页头</span>
        </p>
      </template>
      <p>我是弹窗内容...</p>
      <p>我是弹窗内容...</p>
      <p>我是弹窗内容...</p>
      <template #footer>
        <b-button type="danger">Delete</b-button>
      </template>
    </b-modal>

    <b-modal v-model="modal2">
      <p>我是弹窗内容...</p>
      <p>我是弹窗内容...</p>
      <p>我是弹窗内容...</p>
    </b-modal>

    <b-modal v-model="modal3" title="自定义宽度" width="300px">
      <p>
        自定义宽度,单位 px,默认 520px。 对话框的宽度是响应式的,当屏幕尺寸小于 768px
        时,宽度会变为自动auto。
      </p>
    </b-modal>

    <b-modal v-model="modal4" title="距离顶部" top="200px">
      <p>距离顶部200px</p>
    </b-modal>

    <b-modal v-model="modal5" title="body-style" :body-styles="{ padding: '20px' }">
      <p>我是弹窗内容...</p>
      <p>我是弹窗内容...</p>
      <p>我是弹窗内容...</p>
    </b-modal>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'

const modal1 = ref(false)
const modal2 = ref(false)
const modal3 = ref(false)
const modal4 = ref(false)
const modal5 = ref(false)
</script>

屏幕居中样式

设置属性 screen-center 对话框可以居中进行显示,并且,可以设置默认最大高度。

<template>
  <div>
    <b-button @click="open1">自适应高度居中弹窗</b-button>
    <b-button @click="open2">居中弹窗</b-button>

    <b-modal v-model="visible" title="普通的模态框标题" screen-center>
      <p v-for="i in rows" :key="i">我是弹窗内容...</p>
      <template #footer>
        <span>
          <b-button @click="onClose">取 消</b-button>
          <b-button type="primary" @click="onClose">确 定</b-button>
        </span>
      </template>
    </b-modal>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'

const visible = ref(false)
const rows = ref(5)

function open1() {
  visible.value = true
  rows.value = 30
}

function open2() {
  visible.value = true
  rows.value = 3
}

function onClose() {
  visible.value = false
}
</script>
<template>
  <div>
    <b-button @click="open1">自适应高度居中弹窗</b-button>
    <b-button @click="open2">居中弹窗</b-button>

    <b-modal v-model="visible" title="普通的模态框标题" screen-center>
      <p v-for="i in rows" :key="i">我是弹窗内容...</p>
      <template #footer>
        <span>
          <b-button @click="onClose">取 消</b-button>
          <b-button type="primary" @click="onClose">确 定</b-button>
        </span>
      </template>
    </b-modal>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'

const visible = ref(false)
const rows = ref(5)

function open1() {
  visible.value = true
  rows.value = 30
}

function open2() {
  visible.value = true
  rows.value = 3
}

function onClose() {
  visible.value = false
}
</script>

弹出动画

弹窗动画可以通过 transition-name 自定义,默认从点击位置弹出

<template>
  <div>
    <b-space>
      <b-radio-group v-model="transitionName" type="capsule">
        <b-radio label="dialog-fade"></b-radio>
        <b-radio label="fade-in"></b-radio>
        <b-radio label="move-right"></b-radio>
        <b-radio label="zoom-in-top"></b-radio>
        <b-radio label="zoom-in"></b-radio>
        <b-radio label="fade-scale-move"></b-radio>
        <b-radio label="fade-down"></b-radio>
      </b-radio-group>
      <b-button @click="modal1 = true">弹出</b-button>
    </b-space>

    <b-modal
      v-model="modal1"
      :title="`自定义动画${transitionName}`"
      :transition-name="transitionName"
    >
      <p>我是弹窗内容...</p>
      <p>我是弹窗内容...</p>
      <p>我是弹窗内容...</p>
      <template #footer>
        <span>
          <b-button @click="modal1 = false">关闭</b-button>
        </span>
      </template>
    </b-modal>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'

const modal1 = ref(false)
const transitionName = ref('dialog-fade')
</script>
<template>
  <div>
    <b-space>
      <b-radio-group v-model="transitionName" type="capsule">
        <b-radio label="dialog-fade"></b-radio>
        <b-radio label="fade-in"></b-radio>
        <b-radio label="move-right"></b-radio>
        <b-radio label="zoom-in-top"></b-radio>
        <b-radio label="zoom-in"></b-radio>
        <b-radio label="fade-scale-move"></b-radio>
        <b-radio label="fade-down"></b-radio>
      </b-radio-group>
      <b-button @click="modal1 = true">弹出</b-button>
    </b-space>

    <b-modal
      v-model="modal1"
      :title="`自定义动画${transitionName}`"
      :transition-name="transitionName"
    >
      <p>我是弹窗内容...</p>
      <p>我是弹窗内容...</p>
      <p>我是弹窗内容...</p>
      <template #footer>
        <span>
          <b-button @click="modal1 = false">关闭</b-button>
        </span>
      </template>
    </b-modal>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'

const modal1 = ref(false)
const transitionName = ref('dialog-fade')
</script>

禁用关闭

可以禁用关闭和遮罩层关闭。

<template>
  <div>
    <b-button @click="modal1 = true">禁用右上角关闭</b-button>
    <b-button @click="modal2 = true">禁用mask关闭</b-button>
    <b-modal v-model="modal1" title="普通的模态框标题" :show-close="false">
      <p>禁用右上角关闭</p>
    </b-modal>
    <b-modal v-model="modal2" title="普通的模态框标题" :mask-closable="false">
      <p>禁用mask关闭</p>
    </b-modal>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'

const modal1 = ref(false)
const modal2 = ref(false)
</script>
<template>
  <div>
    <b-button @click="modal1 = true">禁用右上角关闭</b-button>
    <b-button @click="modal2 = true">禁用mask关闭</b-button>
    <b-modal v-model="modal1" title="普通的模态框标题" :show-close="false">
      <p>禁用右上角关闭</p>
    </b-modal>
    <b-modal v-model="modal2" title="普通的模态框标题" :mask-closable="false">
      <p>禁用mask关闭</p>
    </b-modal>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'

const modal1 = ref(false)
const modal2 = ref(false)
</script>

嵌套

弹窗嵌套一般情况下不推荐嵌套,但也可以这么使用

<template>
  <div>
    <b-button @click="modal1 = true">显示弹窗一</b-button>

    <b-modal v-model="modal1" title="弹窗一" width="600px">
      <p>我是弹窗内容...</p>
      <p>我是弹窗内容...</p>
      <p>我是弹窗内容...</p>
      <b-button type="primary" @click="modal2 = true">打开嵌套弹窗</b-button>
      <b-modal v-model="modal2" title="嵌套弹窗">
        <p>我是弹窗内容...</p>
        <p>我是弹窗内容...</p>
        <p>我是弹窗内容...</p>
      </b-modal>
    </b-modal>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'

const modal1 = ref(false)
const modal2 = ref(false)
</script>
<template>
  <div>
    <b-button @click="modal1 = true">显示弹窗一</b-button>

    <b-modal v-model="modal1" title="弹窗一" width="600px">
      <p>我是弹窗内容...</p>
      <p>我是弹窗内容...</p>
      <p>我是弹窗内容...</p>
      <b-button type="primary" @click="modal2 = true">打开嵌套弹窗</b-button>
      <b-modal v-model="modal2" title="嵌套弹窗">
        <p>我是弹窗内容...</p>
        <p>我是弹窗内容...</p>
        <p>我是弹窗内容...</p>
      </b-modal>
    </b-modal>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'

const modal1 = ref(false)
const modal2 = ref(false)
</script>

全屏

设置属性 fullscreen 可以全屏显示。并且可以设置不同的控制器来自定义控制

<template>
  <div>
    <b-button @click="modal = true">显示全屏对话框</b-button>
    <b-modal v-model="modal" title="全屏标题" :fullscreen="fullscreen">
      <template #ctrl>
        <i
          :class="`b-iconfont b-icon-fullscreen${fullscreen ? '-exit' : ''}`"
          @click="fullscreen = !fullscreen"
        ></i>
      </template>
      <div :style="fullscreen ? {} : 'height: 300px; overflow-y: auto'">
        <p v-for="i in 50" :key="i">我是全屏的内容{{ i }}...</p>
      </div>
      <template #footer>
        <span>
          <b-button @click="modal = false">取 消</b-button>
          <b-button type="primary" @click="modal = false">确 定</b-button>
        </span>
      </template>
    </b-modal>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'

const modal = ref(false)
const fullscreen = ref(false)
</script>
<template>
  <div>
    <b-button @click="modal = true">显示全屏对话框</b-button>
    <b-modal v-model="modal" title="全屏标题" :fullscreen="fullscreen">
      <template #ctrl>
        <i
          :class="`b-iconfont b-icon-fullscreen${fullscreen ? '-exit' : ''}`"
          @click="fullscreen = !fullscreen"
        ></i>
      </template>
      <div :style="fullscreen ? {} : 'height: 300px; overflow-y: auto'">
        <p v-for="i in 50" :key="i">我是全屏的内容{{ i }}...</p>
      </div>
      <template #footer>
        <span>
          <b-button @click="modal = false">取 消</b-button>
          <b-button type="primary" @click="modal = false">确 定</b-button>
        </span>
      </template>
    </b-modal>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'

const modal = ref(false)
const fullscreen = ref(false)
</script>

可拖拽

设置属性 draggable 对话框可以进行拖拽移动。

<template>
  <div>
    <b-button @click="modal1 = true">打开弹窗1</b-button>
    <b-button @click="modal2 = true">打开弹窗2</b-button>
    <b-modal v-model="modal1" title="弹窗1" draggable>
      <p>弹窗1内容</p>
    </b-modal>
    <b-modal v-model="modal2" title="弹窗2" draggable :mask="false">
      <p>弹窗2内容</p>
    </b-modal>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'

const modal1 = ref(false)
const modal2 = ref(false)
</script>
<template>
  <div>
    <b-button @click="modal1 = true">打开弹窗1</b-button>
    <b-button @click="modal2 = true">打开弹窗2</b-button>
    <b-modal v-model="modal1" title="弹窗1" draggable>
      <p>弹窗1内容</p>
    </b-modal>
    <b-modal v-model="modal2" title="弹窗2" draggable :mask="false">
      <p>弹窗2内容</p>
    </b-modal>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'

const modal1 = ref(false)
const modal2 = ref(false)
</script>

Props

参数说明类型可选值默认值
v-model是否显示Booleanfalse
title标题,如果使用 slot 自定义了页头,则 title 无效String
width对话框宽度String520px
top对话框距离顶部高度String100px
show-close右上角的关闭按钮Booleantrue
mask-closable是否允许点击遮罩层关闭Booleantrue
esc-closable是否允许esc键盘关闭Booleantrue
fullscreen是否全屏显示Booleanfalse
draggable是否可以拖拽移动Booleanfalse
mask是否显示遮罩层Booleantrue
mask-class自定义遮罩类名String
custom-class自定义类名String
body-styles自定body的样式styleObject
z-index层级Number,默认为2000,弹窗会自增,如设置了此值,则会从当前设置的值进行自增0
append-to-body是否将对话框放置于 body 内Booleanfalse
lock-scroll出现modal时锁定滚动Booleantrue
transition-name弹窗动画String'dialog-fade'
open-delay打开延时(毫秒)Number0
close-delay关闭延时(毫秒)Number0
before-close关闭前回调,会暂停关闭Function(done) done用于关闭
destroy-on-close关闭时销毁内部元素,多用于内部元素需要初始化Booleanfalse
screen-center屏幕居中弹窗(水平垂直居中)Booleanfalse
max-height最大弹窗高度(屏幕居中时生效)String'calc(100vh - 80px)'

Events

事件名说明返回值
openmodal打开回调
opened打开动画完成回调
closemodal关闭回调
closed关闭动画结束回调

Slot

名称说明
title自定义标题
ctrl关闭按钮左侧控制槽
footer自定义页脚内容