Dialog 对话框

示例

尺寸与全屏

可选的 ui 属性值:s/m/narrow/medium/wide/auto

s/m 用于指定内容的尺寸,会被继承到内部的组件上。而 narrow/medium/wide/fullscreen/auto 是对话框本身所占区域的大小,可以与 s/m 混合使用。

<template>
<article>
  <veui-button @click="openDialog('s')">
    s
  </veui-button>
  <veui-button @click="openDialog('m')">
    m
  </veui-button>
  <veui-button @click="openDialog('narrow')">
    narrow
  </veui-button>
  <veui-button @click="openDialog('medium')">
    medium
  </veui-button>
  <veui-button @click="openDialog('wide')">
    wide
  </veui-button>
  <veui-button @click="openDialog('fullscreen')">
    fullscreen
  </veui-button>
  <veui-button @click="openDialog('auto')">
    auto
  </veui-button>
  <veui-dialog
    title="System"
    :ui="ui"
    :open.sync="open"
  >
    <p>Current UI: "{{ ui }}"</p>
    <p v-if="ui === 's' || ui === 'm'">
      <veui-button>Button size: {{ ui }}</veui-button>
      <veui-switch>{{ ui }}</veui-switch>
    </p>
  </veui-dialog>
</article>
</template>

<script>
import { Dialog, Button, Switch } from 'veui'

export default {
  components: {
    'veui-dialog': Dialog,
    'veui-button': Button,
    'veui-switch': Switch
  },
  data () {
    return {
      open: false,
      ui: null
    }
  },
  methods: {
    openDialog (size) {
      this.ui = size
      this.open = true
    }
  }
}
</script>

模态与非模态

<template>
<article>
  <veui-button @click="modalOpen = true">
    Modal
  </veui-button>
  <veui-button @click="nonModalOpen = true">
    Non-modal
  </veui-button>
  <veui-dialog
    title="System"
    :open.sync="modalOpen"
    @ok="handleModalClose(true)"
    @cancel="handleModalClose"
  >
    Do you want to refresh the page?
  </veui-dialog>
  <veui-dialog
    title="System"
    :open.sync="nonModalOpen"
    :modal="false"
    @ok="handleModalClose(true)"
    @cancel="handleModalClose"
  >
    Do you want to refresh the page?
  </veui-dialog>
</article>
</template>

<script>
import { Dialog, Button } from 'veui'

export default {
  components: {
    'veui-dialog': Dialog,
    'veui-button': Button
  },
  data () {
    return {
      modalOpen: false,
      nonModalOpen: false
    }
  },
  methods: {
    handleModalClose (ok) {
      this.modalOpen = false
      if (ok) {
        location.reload()
      }
    },
    handleNonModalClose (ok) {
      this.nonModalOpen = false
      if (ok) {
        location.reload()
      }
    }
  }
}
</script>

自定义内容

<template>
<article>
  <veui-button @click="simpleOpen = true">
    Title & content
  </veui-button>
  <veui-dialog
    :open.sync="simpleOpen"
    title="Customized Title & Content"
    @ok="simpleOpen = false"
    @cancel="simpleOpen = false"
  >
    Customized content via <code>&lt;slot&gt;</code>.
  </veui-dialog>

  <veui-button @click="titleIconOpen = true">
    Icon in Title
  </veui-button>
  <veui-dialog
    :open.sync="titleIconOpen"
    @ok="titleIconOpen = false"
    @cancel="titleIconOpen = false"
  >
    <template #title>
      Title with Icon <veui-icon name="flag"/>
    </template>
    Customized content via <code>&lt;slot&gt;</code>.
  </veui-dialog>

  <veui-button @click="footOpen = true">
    Foot
  </veui-button>
  <veui-dialog
    :open.sync="footOpen"
    title="Customized Foot"
  >
    Customized content via <code>&lt;slot&gt;</code>.
    <template #foot="{ close }">
      <veui-button
        ui="s primary"
        @click="close('ok')"
      >
        Close
      </veui-button>
    </template>
  </veui-dialog>
</article>
</template>

<script>
import { Dialog, Button, Icon } from 'veui'
import 'veui-theme-dls-icons/flag'

export default {
  components: {
    'veui-dialog': Dialog,
    'veui-button': Button,
    'veui-icon': Icon
  },
  data () {
    return {
      simpleOpen: false,
      titleIconOpen: false,
      footOpen: false
    }
  }
}
</script>

异步支持

当你希望统一处理用户可能触发对话框关闭的操作,请使用 before-close 属性传入统一的处理函数,此时无论是点击“确定”/“取消”按钮、关闭按钮还是按下 esc 触发的关闭操作,都会统一进入 before-close 的处理流程。如果逻辑相对简单,比如取消时没有额外逻辑,可以直接操作 open 属性来关闭对话框。

<template>
<article>
  <veui-button
    :disabled="submitting"
    @click="submitOpen = true"
  >
    Submit
  </veui-button>
  <veui-button
    :disabled="saving"
    @click="saveOpen = true"
  >
    Save
  </veui-button>
  <veui-dialog
    title="System"
    :open.sync="submitOpen"
    :before-close="submit"
    :closable="false"
    :escapable="!submitting"
    :loading="submitting"
  >
    Confirm to create the issue?
  </veui-dialog>
  <veui-dialog
    title="System"
    :open.sync="saveOpen"
    :closable="false"
    :escapable="!submitting"
  >
    Confirm to save the post?
    <template #foot>
      <veui-button
        ui="primary"
        :loading="saving"
        @click="save('ok')"
      >
        OK
      </veui-button>
      <veui-button
        :disabled="saving"
        @click="save"
      >
        Cancel
      </veui-button>
    </template>
  </veui-dialog>
</article>
</template>

<script>
import { Dialog, Button } from 'veui'
import toast from 'veui/managers/toast'

function fakeRequest () {
  return new Promise(resolve =>
    setTimeout(() => {
      resolve(Math.random() < 0.5)
    }, 2000)
  )
}

export default {
  components: {
    'veui-dialog': Dialog,
    'veui-button': Button
  },
  data () {
    return {
      submitOpen: false,
      saveOpen: false,
      submitting: false,
      saving: false
    }
  },
  methods: {
    submit (type) {
      if (type === 'ok') {
        this.submitting = true
        return fakeRequest().then(success => {
          this.submitting = false
          if (!success) {
            toast.error('Failed to create the issue. Please retry.')
            return false
          }
          toast.success('Issue created successfully!')
        })
      }
    },
    save (type) {
      if (type === 'ok') {
        this.saving = true
        return fakeRequest().then(success => {
          this.saving = false
          if (!success) {
            toast.error('Failed to save the post. Please retry.')
          } else {
            toast.success('Post saved successfully!')
            this.saveOpen = false
          }
        })
      }
      this.saveOpen = false
    }
  }
}
</script>

可拖拽

<template>
<article>
  <veui-button @click="draggableOpen = true">
    Draggable
  </veui-button>
  <veui-dialog
    :open.sync="draggableOpen"
    title="Draggable Dialog"
    draggable
    @ok="draggableOpen = false"
    @cancel="draggableOpen = false"
  >
    This dialog is draggable.
  </veui-dialog>
</article>
</template>

<script>
import { Dialog, Button } from 'veui'

export default {
  components: {
    'veui-dialog': Dialog,
    'veui-button': Button
  },
  data () {
    return {
      draggableOpen: false
    }
  }
}
</script>

层叠顺序

同时打开上面两个对话框,将一个拖动到使两个对话框稍稍重叠的位置。然后当你点击激活一个对话框,它就将显示于另一个之上了。

<template>
<article>
  <veui-button @click="aOpen = true">
    Dialog A
  </veui-button>
  <veui-dialog
    :open.sync="aOpen"
    title="Dialog A"
    draggable
    :modal="false"
    @ok="aOpen = false"
    @cancel="aOpen = false"
  >
    The content of Dialog A.
  </veui-dialog>

  <veui-button @click="bOpen = true">
    Dialog B
  </veui-button>
  <veui-dialog
    :open.sync="bOpen"
    title="Dialog B"
    draggable
    :modal="false"
    @ok="bOpen = false"
    @cancel="bOpen = false"
  >
    The content of Dialog B.
  </veui-dialog>
</article>
</template>

<script>
import { Dialog, Button } from 'veui'

export default {
  components: {
    'veui-dialog': Dialog,
    'veui-button': Button
  },
  data () {
    return {
      aOpen: false,
      bOpen: false
    }
  }
}
</script>

Loading or Disabled

<template>
<article>
  <div class="op-wrap">
    <veui-button @click="aOpen = true">
        Open Dialog
    </veui-button>
    <veui-checkbox v-model="loading">Loading</veui-checkbox>
    <veui-checkbox class="ml-3p" v-model="disabled">Disabled</veui-checkbox>
  </div>
  <veui-dialog
    :open.sync="aOpen"
    title="Dialog A"
    :loading="loading"
    :disabled="disabled"
  >
    The content of Dialog A.
  </veui-dialog>
</article>
</template>

<script>
import { Dialog, Button, Checkbox } from 'veui'

export default {
  components: {
    'veui-dialog': Dialog,
    'veui-button': Button,
    'veui-checkbox': Checkbox
  },
  data () {
    return {
      aOpen: false,
      disabled: false,
      loading: false
    }
  }
}
</script>

API

属性

名称类型默认值描述
uistring=-

预设样式。

描述
s小内容尺寸(内容及部件尺寸,非对话框整体空间大小)。
m中内容尺寸(内容及部件尺寸,非对话框整体空间大小)。
narrow窄尺寸样式。
medium中尺寸样式。
wide宽尺寸样式。
fullscreen全屏尺寸样式。
auto自适应尺寸样式。
modalboolean=true是否是模态对话框。模态对话框默认遮挡底层(无法点击)且抢占焦点(关闭后焦点会回归)。
titlestring=-对话框标题文本。如果指定了 title 插槽,则优先使用 title 插槽。
openbooleanfalse

.sync

是否显示对话框。

closableboolean=true是否显示关闭按钮。
outside-closableboolean=false点击对话框外部时是否关闭对话框。
draggableboolean=false是否可拖拽。
escapableboolean=false按下 esc 键是否可以关闭对话框。仅在 closabletrue 时生效。
inlineboolean=false是否内联在内容中显示并占用内容空间。
footlessboolean=false是否不显示默认的底部操作栏。
loadingboolean=false是否处于加载状态。处于加载状态时确定按钮也将进入加载状态,无法点击。
disabledboolean=false是否处于禁用状态。处于加载状态时确定按钮也将进入禁用状态,无法点击。
prioritynumber=-对话框浮层层叠权重,参考 Overlay 组件的 priority 属性。
before-closefunction(string): boolean=|Promise<boolean=>-

在将触发对话框关闭的操作发生后执行,类型为 function(type: string): boolean=|Promise<boolean=>type 为触发关闭的类型,默认情况下可选值为 'ok'|'cancel'。返回值可以是一个 boolean,也可以是一个 resolve booleanPromise,用来处理可能需要异步决定对话框关闭状态的情况。返回值或 resolve 值非 false 时才会关闭对话框。

<veui-dialog :open.sync="dialogOpen" :before-close="submit">...</veui-dialog>
methods: {
  submit (type) {
    if (type === 'ok') {
      return axios.post('/item/create', {/* ... */})
        .then(({ id, error }) => {
          if (error) {
            this.showError(error)
            return false // resolve `false` 将阻止对话框关闭
          }
        })
    }
    // resolve 但不返回 `false` 时会关闭对话框
  },
  // ...
}
overlay-classstring|Object=-对话框浮层根元素类名,参考 Overlay 组件的 overlay-class 属性。

插槽

名称描述
default内容区。
title标题区。若同时指定了 title 属性和 title 插槽,以后者为准。
foot

底部区域,默认会展示“确定”、“取消”按钮。

名称类型描述
closefunction(type: string): void触发对话框关闭的回调函数。type 为关闭的类型,将作为参数传入 before-close 钩子函数作为参数,同时将同步触发同名的事件。

事件

名称描述
ok点击“确定”按钮时或通过调用作用域函数 close('ok') 时触发。
cancel点击“取消”按钮、关闭按钮、通过 esc 关闭对话框时,或者通过调用作用域函数 close('cancel') 时触发。
<value>通过调用作用域函数 close(value) 时触发。
afterclose浮层关闭后触发。如果样式主题提供了退出动画,将在退出动画完毕后触发。

图标

名称描述
close关闭。