Dialog 插件

Quasar 的 Dialog(对话框)提供了一种很棒的交互方式,通过对话框向用户展示重要信息,或请求用户做出决策。

从 UI 角度来看,对话框更像是浮动的模态框,它只遮挡了部分屏幕。也就是说,对话框更适用于处理用户的快速操作。

提示

对话框还可以用作 Vue 文件模板中的组件(用于复杂用例,如表单组件、可选选项等)。详见 QDialog

与 QDialog 组件相比,使用 Dialog 插件的优点是可以从 Vue 文件外部调用,并且不需要管理它们的模板。缺点是,它的自定义灵活度更低。

但是,也可以提供一个组件供 Dialog 插件渲染(参见“调用自定义组件”一节),这样既可以避免使用内联对话框让 Vue 模板变得混乱,还可以更好地组织项目文件,并能更好地复用对话框。

使用 Dialog 插件,可以构建以下三种对话框:

  1. Prompt 对话框 - 收集用户输入的字段。
  2. Options 对话框 - 提供一组选项供用户选择,包括单选框(单选)、复选框(多选),以及切换按钮。
  3. 简单的确认对话框,用户可以取消或确认操作或输入。

创建第 1 种收集输入类型的对话框,需要将 prompt 填入到 opts 对象中。

创建第 2 种处理选择类型的对话框,需要将 options 填入到 opts 对象中。

Dialog API

Loading Dialog API...

安装


// quasar.config.js

return {
  framework: {
    plugins: [
      'Dialog'
    ]
  }
}

用法

// Vue 文件之外
import { Dialog } from 'quasar'
(Object) Dialog.create({ ... })

// Vue 文件之内
import { useQuasar } from 'quasar'

setup () {
  const $q = useQuasar()
  $q.dialog({ ... }) // 返回对象
}

请查看 API 中列出的函数返回值对象。

内置用法

提示

查看下列示例时,还应在浏览器的控制台中查看打印输出。

警告

下列 Dialog 插件的示例用法只覆盖了部分内容,更多用法详见 API 中的说明。













基础验证

使用基础验证系统,以便用户在填写预期值之前无法提交对话框(单击/点击“确定”或按 ENTER 键)。







进度条




使用 HTML

设置 html:true 属性后,就可以在对话框的标题和展示信息上使用自定义的 HTML,注意,这种方式可能会遭受 XSS 攻击,因此,一定要清理,并验证用户输入的所有信息。




调用自定义组件

可以使用自定义组件取代 Dialog 插件的默认组件,将其作为对话框的内容,但这时需要自行处理所有的细节(包括自定义组件的 props)。

这个特性其实是 Dialog 插件的基本功能,通过分离和复用对话框的代码,可以使 Vue 组件中其他的模板代码更整洁。

import { useQuasar } from 'quasar'
import CustomComponent from '..path.to.component..'

setup () {
  const $q = useQuasar()

  $q.dialog({
    component: CustomComponent,

    // 转发到自定义组件的 props
    componentProps: {
      text: 'something',
      // ...更多..props...
    }
  }).onOk(() => {
    console.log('OK')
  }).onCancel(() => {
    console.log('Cancel')
  }).onDismiss(() => {
    console.log('Called on OK or Cancel')
  })
}

选项式 API 中,可直接使用 this.$q.dialog({ ... }),与上面组合式 API 代码是等价的。

警告

自定义组件必须遵循下面描述的接口,以便完美地与 Dialog 插件挂钩。注意,带有 REQUIRED 的注释,并将其视为基本用法的示例。

单文件组件搭配 setup 语法糖示例(组合式 API)

组合式 API 中,可以使用 useDialogPluginComponent 组合式函数。

<template>
  <q-dialog ref="dialogRef" @hide="onDialogHide">
    <q-card class="q-dialog-plugin">
      <!--
        ...内容
        ...使用 q-card-section?
      -->

      <!-- 按钮示例 -->
      <q-card-actions align="right">
        <q-btn color="primary" label="OK" @click="onOKClick" />
        <q-btn color="primary" label="Cancel" @click="onDialogCancel" />
      </q-card-actions>
    </q-card>
  </q-dialog>
</template>

<script setup>
import { useDialogPluginComponent } from 'quasar'

const props = defineProps({
  // ...自定义 props
})

defineEmits([
  // REQUIRED; 需要明确指出
  // 组件通过 useDialogPluginComponent() 暴露哪些事件
  ...useDialogPluginComponent.emits
])

const { dialogRef, onDialogHide, onDialogOK, onDialogCancel } = useDialogPluginComponent()
// dialogRef      - 用在 QDialog 上的 Vue ref 模板引用
// onDialogHide   - 处理 QDialog 上 @hide 事件的函数
// onDialogOK     - 对话框结果为 ok 时会调用的函数
//                    示例: onDialogOK() - 不带参数
//                    示例: onDialogOK({ /*.../* }) - 带参数
// onDialogCancel - 对话框结果为 cancel 时调用的函数

// 这是示例的内容,不是必需的
function onOKClick () {
  // REQUIRED! 对话框的结果为 ok 时,必须调用 onDialogOK()  (参数是可选的)
  onDialogOK()
  // 带参数的版本: onDialogOK({ ... })
  // ...会自动关闭对话框
}
</script>

如需以对象的格式定义 emits,可使用以下方式。(需要 Quasar v2.2.5+):

defineEmits({
  // REQUIRED; 需要明确指出
  // 组件通过 useDialogPluginComponent()暴露哪些事件
  ...useDialogPluginComponent.emitsObject,

  // ...自定义的 emits
})

组合式 API 示例

组合式 API 中,可以使用 useDialogPluginComponent 组合式函数。

<template>
  <!-- 注意这里的 dialogRef  -->
  <q-dialog ref="dialogRef" @hide="onDialogHide">
    <q-card class="q-dialog-plugin">
      <!--
        ...内容
        ...使用 q-card-section?
      -->

      <!-- 按钮示例 -->
      <q-card-actions align="right">
        <q-btn color="primary" label="OK" @click="onOKClick" />
        <q-btn color="primary" label="Cancel" @click="onCancelClick" />
      </q-card-actions>
    </q-card>
  </q-dialog>
</template>

<script>
import { useDialogPluginComponent } from 'quasar'

export default {
  props: {
    // ...自定义的 props
  },

  emits: [
  // REQUIRED; 需要明确指出
  // 组件通过 useDialogPluginComponent() 暴露哪些事件
    ...useDialogPluginComponent.emits
  ],

  setup () {
    // REQUIRED; 必须在 setup()函数中调用
    const { dialogRef, onDialogHide, onDialogOK, onDialogCancel } = useDialogPluginComponent()
    // dialogRef      - 用在 QDialog 上的 Vue ref 模板引用
    // onDialogHide   - 处理 QDialog 上 @hide 事件的函数
    // onDialogOK     - 对话框结果为 ok 时调用的函数
    //                    示例: onDialogOK() - 不带参数
    //                    示例: onDialogOK({ /*.../* }) - 带参数
    // onDialogCancel - 对话框结果为 cancel 时会调用的函数

    return {
      // 这里是 REQUIRED !
      // 需要将来自 useDialogPluginComponent()注入到 Vue 模板中
      dialogRef,
      onDialogHide,

      // 一些别的需要在 Vue 模板中使用的方法
      onOKClick () {
        // REQUIRED!对话框的结果为 ok 时必须调用 onDialogOK() ,(参数是可选的)
        onDialogOK()
        // 带参数的版本: onDialogOK({ ... })
        // ...它也会自动关闭对话框
      }

      // 可直接透传 onDialogCancel
      onCancelClick: onDialogCancel
    }
  }
}
</script>

如需通过对象的格式定义 emits (需要 Quasar v2.2.5+):

emits: {
  // REQUIRED; 需要明确指出
  // 组件通过 useDialogPluginComponent() 暴露哪些事件
  ...useDialogPluginComponent.emitsObject,

  // ...自定义的 emits
]

选项式 API 示例

<template>
  <q-dialog ref="dialog" @hide="onDialogHide">
    <q-card class="q-dialog-plugin">
      <!--
        ...内容
        ...使用 q-card-section?
      -->

      <!-- 按钮示例 -->
      <q-card-actions align="right">
        <q-btn color="primary" label="OK" @click="onOKClick" />
        <q-btn color="primary" label="Cancel" @click="onCancelClick" />
      </q-card-actions>
    </q-card>
  </q-dialog>
</template>

<script>
export default {
  props: {
    // ...自定义的 props
  },

  emits: [
    // REQUIRED
    'ok', 'hide'
  ],

  methods: {
    //  REQUIRED 下的函数都是必须的
    // (不要修改这个函数名 --> "show")
    show () {
      this.$refs.dialog.show()
    },

    //  REQUIRED 下的函数都是必须的
    // (不要修改这个函数名 --> "hide")
    hide () {
      this.$refs.dialog.hide()
    },

    onDialogHide () {
      // 需要在 QDialog 触发 “hide” 事件时触发
      this.$emit('hide')
    },

    onOKClick () {
      // REQUIRED
      // 对话框结果为 ok 时,必须触发 ok 事件 (参数是可选的)
      // 在关闭对话框之前
      this.$emit('ok')
      // 或带参数的版本: this.$emit('ok', { ... })

      // 然后关闭对话框
      this.hide()
    },

    onCancelClick () {
      // 操作取消时,只需关闭对话框
      this.hide()
    }
  }
}
</script>

处理 Cordova/Capacitor 返回按钮

Quasar 默认处理返回按钮,所以它会关闭打开的对话框,而不是默认返回到前一页(这样的用户体验并不好)。

如需禁用此行为,需编辑 /quasar.config.js:

// quasar.config.js;
// 仅用于 Cordova!
return {
  framework: {
    config: {
      cordova: {
        // quasar 处理手机返回键使应用程序退出
        backButtonExit: true/false/'*'/['/login', '/home', '/my-page'],

        // 下面这个配置开启会完全禁用 quasar 管理手机的返回按钮
        backButton: true/false
      }
    }
  }
}

// quasar.config.js;
// 仅用于 Capacitor!
return {
  framework: {
    config: {
      capacitor: {
        // quasar 处理手机返回键使应用程序退出
        backButtonExit: true/false/'*'/['/login', '/home', '/my-page'],

        // 开启下面这个配置会完全禁用 quasar 管理手机的返回按钮
        backButton: true/false
      }
    }
  }
}

类型定义

查看类型定义
type InputType =
  | "button"
  | "checkbox"
  | "color"
  | "date"
  | "datetime-local"
  | "email"
  | "file"
  | "hidden"
  | "image"
  | "month"
  | "number"
  | "password"
  | "radio"
  | "range"
  | "reset"
  | "search"
  | "submit"
  | "tel"
  | "text"
  | "time"
  | "url"
  | "week";
type DatalessInputType = Extract<InputType, "submit" | "reset">;

type PromptInputType = "textarea" | Exclude<InputType, DatalessInputType>;

type DataAttributes = {
  
  [dataAttributes in `data-${string}`]?: any;
} & {
  "data-cy"?: string;
};

export type QDialogInputPrompt<T = string> = {
  /**
   * The initial value of the input
   */
  model: T;
  /**
   * Optional property to determine the input field type
   *
   * @defaultValue "text"
   */
  type?: PromptInputType;

  /**
   * Is typed content valid?
   *
   * @param val The value of the input
   * @returns The text passed validation or not
   */
  isValid?: (value: T) => boolean;
} & Partial<Omit<QInputProps, "modelValue" | "onUpdate:modelValue" | "type">> &
  Omit<InputHTMLAttributes, "type"> &
  DataAttributes;

type SelectionPromptType = NonNullable<QOptionGroupProps["type"]>;
export type QDialogSelectionPrompt<
  
  
  
  TType extends SelectionPromptType = SelectionPromptType,
  TModel = TType extends "radio" ? string : readonly any[],
> = {
  /**
   * The value of the selection
   * If the `type` is "radio"(default), the value is a string, otherwise it's an array
   */
  model: TModel;

  /**
   * The type of the selection
   *
   * @defaultValue "radio"
   */
  type?: TType;

  /**
   * The list of options to interact with
   * Equivalent to `options` prop of the `QOptionGroup` component
   */
  items?: QOptionGroupProps["options"];

  /**
   * Is the model valid?
   *
   * @param model The current model (If the `type` is "radio"(default), the value is a string, otherwise it's an array)
   * @returns The selection passed validation or not
   */
  isValid?: (value: TModel) => boolean;
} & Partial<
  Omit<
    QOptionGroupProps,
    "modelValue" | "onUpdate:modelValue" | "type" | "options"
  >
> &
  HTMLAttributes &
  DataAttributes;