Skip to content
API 风格:

Dialog 對話框 ​

強制回應對話框元件,用於展示重要資訊或確認操作。

基礎用法 ​

基礎用法
vue
<script setup lang="ts">
import { ref } from 'vue'
import { LhButton, LhDialog } from '@lh-ui/vue3'

const dialogVisible1 = ref(false)
</script>

<template>
  <!-- 基礎用法 -->
  <LhButton @click="dialogVisible1 = true">打开对话框</LhButton>
  <LhDialog v-model="dialogVisible1" title="提示">
    <p>这是一个对话框内容</p>
    <template #footer>
      <LhButton @click="dialogVisible1 = false">取消</LhButton>
      <LhButton type="primary" @click="dialogVisible1 = false">确定</LhButton>
    </template>
  </LhDialog>
</template>
vue
<script>
import { LhButton, LhDialog } from '@lh-ui/vue3'

export default {
  components: { LhButton, LhDialog },
  data() {
    return {
      dialogVisible1: false
    }
  }
}
</script>

<template>
  <!-- 基礎用法 -->
  <LhButton @click="dialogVisible1 = true">打开对话框</LhButton>
  <LhDialog v-model="dialogVisible1" title="提示">
    <p>这是一个对话框内容</p>
    <template #footer>
      <LhButton @click="dialogVisible1 = false">取消</LhButton>
      <LhButton type="primary" @click="dialogVisible1 = false">确定</LhButton>
    </template>
  </LhDialog>
</template>

自訂寬高 ​

自訂寬度
vue
<script setup lang="ts">
import { ref } from 'vue'
import { LhButton, LhDialog } from '@lh-ui/vue3'

const dialogVisible2 = ref(false)
</script>

<template>
  <!-- 自訂寬高 -->
  <LhButton @click="dialogVisible2 = true">打开大对话框</LhButton>
  <LhDialog v-model="dialogVisible2" title="大对话框" width="600px">
    <p>自定义尺寸的对话框</p>
    <template #footer>
      <LhButton @click="dialogVisible2 = false">关闭</LhButton>
    </template>
  </LhDialog>
</template>
vue
<script>
import { LhButton, LhDialog } from '@lh-ui/vue3'

export default {
  components: { LhButton, LhDialog },
  data() {
    return {
      dialogVisible2: false
    }
  }
}
</script>

<template>
  <!-- 自訂寬高 -->
  <LhButton @click="dialogVisible2 = true">打开大对话框</LhButton>
  <LhDialog v-model="dialogVisible2" title="大对话框" width="600px">
    <p>自定义尺寸的对话框</p>
    <template #footer>
      <LhButton @click="dialogVisible2 = false">关闭</LhButton>
    </template>
  </LhDialog>
</template>

可拖曳 ​

可拖曳
vue
<script setup lang="ts">
import { ref } from 'vue'
import { LhButton, LhDialog } from '@lh-ui/vue3'

const dialogVisible3 = ref(false)
</script>

<template>
  <!-- 可拖曳 -->
  <LhButton @click="dialogVisible3 = true">打开可拖拽对话框</LhButton>
  <LhDialog v-model="dialogVisible3" title="可拖拽对话框" draggable>
    <p>拖拽标题栏可以移动此对话框。</p>
    <template #footer>
      <LhButton @click="dialogVisible3 = false">关闭</LhButton>
    </template>
  </LhDialog>
</template>
vue
<script>
import { LhButton, LhDialog } from '@lh-ui/vue3'

export default {
  components: { LhButton, LhDialog },
  data() {
    return {
      dialogVisible3: false
    }
  }
}
</script>

<template>
  <!-- 可拖曳 -->
  <LhButton @click="dialogVisible3 = true">打开可拖拽对话框</LhButton>
  <LhDialog v-model="dialogVisible3" title="可拖拽对话框" draggable>
    <p>拖拽标题栏可以移动此对话框。</p>
    <template #footer>
      <LhButton @click="dialogVisible3 = false">关闭</LhButton>
    </template>
  </LhDialog>
</template>

自訂主題 ​

為對話框套用自訂主題色。

青花瓷主題對話框
vue
<script setup lang="ts">
import { ref } from 'vue'
import { LhConfigProvider, LhButton, LhDialog } from '@lh-ui/vue3'

const dialogThemeVisible = ref(false)
const cerblueTheme = {
  'primary-color': '#2B4C7C',
  'primary-color-hover': '#3D649E',
  'primary-color-bg': '#E8EDF3',
}
</script>

<template>
  <LhConfigProvider :theme-vars="cerblueTheme">
    <!-- 青花瓷主題 -->
    <LhButton @click="dialogThemeVisible = true" type="primary">打开主题对话框</LhButton>
    <LhDialog v-model="dialogThemeVisible" title="青花瓷主题">
      <p>该对话框使用青花瓷主题色</p>
      <template #footer>
        <LhButton @click="dialogThemeVisible = false">关闭</LhButton>
      </template>
    </LhDialog>
  </LhConfigProvider>
</template>
vue
<script>
import { LhConfigProvider, LhButton, LhDialog } from '@lh-ui/vue3'

export default {
  components: { LhConfigProvider, LhButton, LhDialog },
  data() {
    return {
      dialogThemeVisible: false,
      cerblueTheme: {
        'primary-color': '#2B4C7C',
        'primary-color-hover': '#3D649E',
        'primary-color-bg': '#E8EDF3',
      },
    }
  },
}
</script>

<template>
  <LhConfigProvider :theme-vars="cerblueTheme">
    <!-- 青花瓷主題 -->
    <LhButton @click="dialogThemeVisible = true" type="primary">打开主题对话框</LhButton>
    <LhDialog v-model="dialogThemeVisible" title="青花瓷主题">
      <p>该对话框使用青花瓷主题色</p>
      <template #footer>
        <LhButton @click="dialogThemeVisible = false">关闭</LhButton>
      </template>
    </LhDialog>
  </LhConfigProvider>
</template>

更多主題請參考主題定製。

sx 快速版面配置 ​

透過 sx 屬性快速設定 Dialog 的維度與間距。

sx 快速版面配置
vue
<script setup lang="ts">
import { ref } from 'vue'
import { LhButton, LhDialog } from '@lh-ui/vue3'

const visible = ref(false)
</script>

<template>
  <!-- 開啟對話框 -->
  <LhButton @click="visible = true">打开对话框</LhButton>
  <!-- sx 版面配置對話框 -->
  <LhDialog v-model="visible" title="sx 布局" :sx="{ maxWidth: 400 }">
    <p>设置了最大宽度</p>
    <template #footer>
      <LhButton @click="visible = false">取消</LhButton>
    </template>
  </LhDialog>
</template>
vue
<script>
import { LhButton, LhDialog } from '@lh-ui/vue3'

export default {
  components: { LhButton, LhDialog },
  data() {
    return { visible: false }
  },
}
</script>

<template>
  <!-- 開啟對話框 -->
  <LhButton @click="visible = true">打开对话框</LhButton>
  <!-- sx 版面配置對話框 -->
  <LhDialog v-model="visible" title="sx 布局" :sx="{ maxWidth: 400 }">
    <p>设置了最大宽度</p>
    <template #footer>
      <LhButton @click="visible = false">取消</LhButton>
    </template>
  </LhDialog>
</template>

國際化 ​

對話框文字可以透過 LhConfigProvider 配合語言包實現國際化切換。

國際化
vue
<script setup lang="ts">
import { ref, computed } from 'vue'
import { LhConfigProvider, LhButton, LhDialog, zhCN, enUS } from '@lh-ui/vue3'

const locale = ref('zh-CN')
const i18nVisible = ref(false)
const messages = computed(() => (locale.value === 'zh-CN' ? zhCN : enUS))
</script>

<template>
  <LhConfigProvider :locale="messages">
    <!-- 開啟對話框 -->
    <LhButton @click="i18nVisible = true">
      {{ locale === 'zh-CN' ? '打开对话框' : 'Open Dialog' }}
    </LhButton>
    <!-- 國際化對話框 -->
    <LhDialog v-model="i18nVisible" :title="locale === 'zh-CN' ? '提示' : 'Notice'">
      <p>{{ locale === 'zh-CN' ? '对话框内容' : 'Dialog content' }}</p>
      <template #footer>
        <LhButton @click="i18nVisible = false">
          {{ locale === 'zh-CN' ? '取消' : 'Cancel' }}
        </LhButton>
      </template>
    </LhDialog>
  </LhConfigProvider>
</template>
vue
<script>
import { LhConfigProvider, LhButton, LhDialog, zhCN, enUS } from '@lh-ui/vue3'

export default {
  components: { LhConfigProvider, LhButton, LhDialog },
  data() {
    return {
      locale: 'zh-CN',
      i18nVisible: false,
    }
  },
  computed: {
    messages() {
      return this.locale === 'zh-CN' ? zhCN : enUS
    },
  },
}
</script>

<template>
  <LhConfigProvider :locale="messages">
    <!-- 開啟對話框 -->
    <LhButton @click="i18nVisible = true">
      {{ locale === 'zh-CN' ? '打开对话框' : 'Open Dialog' }}
    </LhButton>
    <!-- 國際化對話框 -->
    <LhDialog v-model="i18nVisible" :title="locale === 'zh-CN' ? '提示' : 'Notice'">
      <p>{{ locale === 'zh-CN' ? '对话框内容' : 'Dialog content' }}</p>
      <template #footer>
        <LhButton @click="i18nVisible = false">
          {{ locale === 'zh-CN' ? '取消' : 'Cancel' }}
        </LhButton>
      </template>
    </LhDialog>
  </LhConfigProvider>
</template>

行為開關 ​

關閉方式 / 捲動鎖定 / beforeClose
vue
<script setup lang="ts">
import { ref } from 'vue'
import { LhButton, LhDialog } from '@lh-ui/vue3'

const dialogAdv1 = ref(false)
const dialogAdv2 = ref(false)
const dialogAdv3 = ref(false)

function handleAdvBeforeClose(done: () => void) {
  setTimeout(done, 500)
}
</script>

<template>
  <!-- 僅按鈕關閉 -->
  <LhButton @click="dialogAdv1 = true">仅按钮关闭</LhButton>
  <LhDialog
    v-model="dialogAdv1"
    title="仅按钮关闭"
    :show-close="false"
    :close-on-click-modal="false"
    :close-on-press-escape="false"
  >
    <p>隐藏右上角关闭按钮,点击遮罩与按 ESC 也不会关闭,只能通过底部按钮关闭。</p>
    <template #footer>
      <LhButton type="primary" @click="dialogAdv1 = false">我知道了</LhButton>
    </template>
  </LhDialog>
  <!-- 不鎖定捲動 -->
  <LhButton @click="dialogAdv2 = true">不锁定滚动</LhButton>
  <LhDialog v-model="dialogAdv2" title="不锁定滚动" :lock-scroll="false">
    <p>对话框打开时页面仍可滚动,适合内容较短的轻量提示。</p>
  </LhDialog>
  <!-- 非同步關閉 -->
  <LhButton @click="dialogAdv3 = true">异步关闭</LhButton>
  <LhDialog v-model="dialogAdv3" title="异步关闭" :before-close="handleAdvBeforeClose">
    <p>点击右上角关闭按钮、遮罩或按 ESC 后,延迟 500ms 才真正关闭(模拟关闭前校验)。</p>
  </LhDialog>
</template>
vue
<script>
import { LhButton, LhDialog } from '@lh-ui/vue3'

export default {
  components: { LhButton, LhDialog },
  data() {
    return {
      dialogAdv1: false,
      dialogAdv2: false,
      dialogAdv3: false,
    }
  },
  methods: {
    handleAdvBeforeClose(done) {
      setTimeout(done, 500)
    },
  },
}
</script>

<template>
  <!-- 僅按鈕關閉 -->
  <LhButton @click="dialogAdv1 = true">仅按钮关闭</LhButton>
  <LhDialog
    v-model="dialogAdv1"
    title="仅按钮关闭"
    :show-close="false"
    :close-on-click-modal="false"
    :close-on-press-escape="false"
  >
    <p>隐藏右上角关闭按钮,点击遮罩与按 ESC 也不会关闭,只能通过底部按钮关闭。</p>
    <template #footer>
      <LhButton type="primary" @click="dialogAdv1 = false">我知道了</LhButton>
    </template>
  </LhDialog>
  <!-- 不鎖定捲動 -->
  <LhButton @click="dialogAdv2 = true">不锁定滚动</LhButton>
  <LhDialog v-model="dialogAdv2" title="不锁定滚动" :lock-scroll="false">
    <p>对话框打开时页面仍可滚动,适合内容较短的轻量提示。</p>
  </LhDialog>
  <!-- 非同步關閉 -->
  <LhButton @click="dialogAdv3 = true">异步关闭</LhButton>
  <LhDialog v-model="dialogAdv3" title="异步关闭" :before-close="handleAdvBeforeClose">
    <p>点击右上角关闭按钮、遮罩或按 ESC 后,延迟 500ms 才真正关闭(模拟关闭前校验)。</p>
  </LhDialog>
</template>

位置與層級 ​

fullscreen / position / top / zIndex / center
vue
<script setup lang="ts">
import { ref } from 'vue'
import { LhButton, LhDialog } from '@lh-ui/vue3'

const dialogAdv4 = ref(false)
const dialogAdv5 = ref(false)
const dialogAdv6 = ref(false)
const dialogAdv7 = ref(false)
</script>

<template>
  <!-- 全螢幕 -->
  <LhButton @click="dialogAdv4 = true">全屏</LhButton>
  <LhDialog v-model="dialogAdv4" title="全屏对话框" fullscreen>
    <p>fullscreen 时对话框铺满整个视口。</p>
  </LhDialog>
  <!-- 底部位置 -->
  <LhButton @click="dialogAdv5 = true">底部位置</LhButton>
  <LhDialog v-model="dialogAdv5" title="底部位置" position="bottom">
    <p>position 为 bottom 时对话框贴近视口底部展示。</p>
  </LhDialog>
  <!-- 頂部偏移+層級 -->
  <LhButton @click="dialogAdv6 = true">顶部偏移 + 层级</LhButton>
  <LhDialog v-model="dialogAdv6" title="顶部偏移 + 层级" position="top" top="10vh" :z-index="3000">
    <p>top 调整距视口顶部的距离,z-index 控制层叠顺序。</p>
  </LhDialog>
  <!-- 內容置中 -->
  <LhButton @click="dialogAdv7 = true">内容居中(center)</LhButton>
  <LhDialog v-model="dialogAdv7" title="内容居中" center>
    <p>center 让标题与内容居中显示(兼容旧版,新代码建议使用 position)。</p>
    <template #footer>
      <LhButton @click="dialogAdv7 = false">取消</LhButton>
      <LhButton type="primary" @click="dialogAdv7 = false">确定</LhButton>
    </template>
  </LhDialog>
</template>
vue
<script>
import { LhButton, LhDialog } from '@lh-ui/vue3'

export default {
  components: { LhButton, LhDialog },
  data() {
    return {
      dialogAdv4: false,
      dialogAdv5: false,
      dialogAdv6: false,
      dialogAdv7: false,
    }
  },
}
</script>

<template>
  <!-- 全螢幕 -->
  <LhButton @click="dialogAdv4 = true">全屏</LhButton>
  <LhDialog v-model="dialogAdv4" title="全屏对话框" fullscreen>
    <p>fullscreen 时对话框铺满整个视口。</p>
  </LhDialog>
  <!-- 底部位置 -->
  <LhButton @click="dialogAdv5 = true">底部位置</LhButton>
  <LhDialog v-model="dialogAdv5" title="底部位置" position="bottom">
    <p>position 为 bottom 时对话框贴近视口底部展示。</p>
  </LhDialog>
  <!-- 頂部偏移+層級 -->
  <LhButton @click="dialogAdv6 = true">顶部偏移 + 层级</LhButton>
  <LhDialog v-model="dialogAdv6" title="顶部偏移 + 层级" position="top" top="10vh" :z-index="3000">
    <p>top 调整距视口顶部的距离,z-index 控制层叠顺序。</p>
  </LhDialog>
  <!-- 內容置中 -->
  <LhButton @click="dialogAdv7 = true">内容居中(center)</LhButton>
  <LhDialog v-model="dialogAdv7" title="内容居中" center>
    <p>center 让标题与内容居中显示(兼容旧版,新代码建议使用 position)。</p>
    <template #footer>
      <LhButton @click="dialogAdv7 = false">取消</LhButton>
      <LhButton type="primary" @click="dialogAdv7 = false">确定</LhButton>
    </template>
  </LhDialog>
</template>

Dialog API ​

Props ​

屬性名說明類型預設值
modelValue是否顯示對話框booleanfalse
title對話框標題string''
width對話框寬度string | number'480px'
fullscreen是否全螢幕booleanfalse
showClose是否顯示關閉按鈕booleantrue
closeOnClickModal點選遮罩層是否關閉booleantrue
closeOnPressEscape按 ESC 是否關閉booleantrue
draggable是否可拖曳booleanfalse
center是否置中顯示(相容舊版,建議使用 position)booleanfalse
position彈窗位置:top / center / bottom"top" | "center" | "bottom"'center'
lockScroll是否鎖定捲動booleantrue
beforeClose關閉前回呼(done: () => void) => void—
top頂部距離(px)string'15vh'
zIndexz-indexnumber—
themeVars元件級主題變數,覆寫 ConfigProvider 設定{ [x: string]: string; }—
bgPattern元件級背景花紋,覆寫 ConfigProvider 設定string—
sxsx 快速版面配置屬性LhSxProps—

Events ​

事件名說明回呼參數
update:modelValue顯示狀態改變(value: boolean)
open開啟動畫結束—
close關閉動畫結束—
opened對話框完全開啟後觸發—
closed對話框完全關閉後觸發—

Slots ​

插槽名說明
default對話框內容
header對話框標題區域
footer對話框底部區域

類型定義 ​

本元件對外匯出的 TypeScript 類型結構如下(自動提取自 packages/components/dialog/src/types.ts 與 @lh-ui/share/core/* 原始碼,點選各條目展開檢視完整定義;屬性說明見上方 Props 表):

LhDialogProps
ts
/**
 * Dialog 元件 Props
 */
export interface LhDialogProps {
  /** 是否顯示 */
  modelValue?: boolean
  /** 標題 */
  title?: string
  /** 寬度 */
  width?: string | number
  /** 是否全螢幕 */
  fullscreen?: boolean
  /** 是否顯示關閉按鈕 */
  showClose?: boolean
  /** 點選遮罩是否關閉 */
  closeOnClickModal?: boolean
  /** 按 ESC 是否關閉 */
  closeOnPressEscape?: boolean
  /** 是否可拖曳 */
  draggable?: boolean
  /** 是否置中顯示(相容舊版,建議使用 position) */
  center?: boolean
  /** 彈窗位置:top / center / bottom */
  position?: 'top' | 'center' | 'bottom'
  /** 是否鎖定捲動 */
  lockScroll?: boolean
  /** 關閉前回呼 */
  beforeClose?: (done: () => void) => void
  /** 頂部距離(px) */
  top?: string
  /** z-index */
  zIndex?: number
  /** 元件級主題變數,覆寫 ConfigProvider 設定 */
  themeVars?: Record<string, string>
  /** 元件級背景花紋,覆寫 ConfigProvider 設定 */
  bgPattern?: string
  /** sx 快速版面配置屬性 */
  sx?: LhSxProps
}