createTemplatePromise
将模板作为 Promise 处理。这对于构建自定义对话框、模态框、提示框等非常有用。
用法
<script setup lang="ts">
import { createTemplatePromise } from '@vueuse/core'
const TemplatePromise = createTemplatePromise<ReturnType>()
async function open() {
const result = await TemplatePromise.start()
// 按钮被点击,结果是 'ok'
}
</script>
<template>
<TemplatePromise v-slot="{ promise, resolve, reject, args }">
<button @click="resolve('ok')">
OK
</button>
</TemplatePromise>
</template>
特性
Programmatic(程序化):将你的 UI 调用为 Promise。Template(模板):使用 Vue 模板进行渲染,而不是新的 DSL。TypeScript:通过泛型提供完全的类型安全。Renderless(无渲染):你完全控制 UI。Transition(过渡):支持 Vue 过渡效果。
此函数是从 vue-template-promise 迁移而来。
使用 createTemplatePromise
createTemplatePromise 返回一个 Vue 组件,你可以直接在 <script setup> 的模板中使用它。
import { createTemplatePromise } from '@vueuse/core'
const TemplatePromise = createTemplatePromise()
const MyPromise = createTemplatePromise<boolean>() // 带有泛型
在模板中,使用 v-slot 访问 promise 和解析函数。
<template>
<TemplatePromise v-slot="{ promise, resolve, reject, args }">
<button @click="resolve('ok')">
OK
</button>
</TemplatePromise>
<MyPromise v-slot="{ promise, resolve, reject, args }">
</MyPromise>
</template>
该插槽最初不会被渲染(类似于 v-if="false"),直到你调用组件的 start 方法。
const result = await TemplatePromise.start()
一旦在模板中调用 resolve 或 reject,Promise 将被解析或拒绝,并返回你传入的值。一旦解析,插槽将自动移除。
传递参数
你可以通过 start 方法传递参数。
import { createTemplatePromise } from '@vueuse/core'
const TemplatePromise = createTemplatePromise<boolean, [string, number]>()
const result = await TemplatePromise.start('hello', 123) // Pr
在模板插槽中,你可以通过 args 属性访问这些参数。
<template>
<TemplatePromise v-slot="{ args, resolve }">
<div>{{ args[0] }}</div>
<!-- hello -->
<div>{{ args[1] }}</div>
<!-- 123 -->
<button @click="resolve(true)">
OK
</button>
</TemplatePromise>
</template>
过渡
你可以使用 过渡来动画化插槽。
<script setup lang="ts">
const TemplatePromise = createTemplatePromise<ReturnType>({
transition: {
name: 'fade',
appear: true,
},
})
</script>
<template>
<TemplatePromise v-slot="{ resolve }">
<button @click="resolve('ok')">
OK
</button>
</TemplatePromise>
</template>
<style scoped>
.fade-enter-active,
.fade-leave-active {
transition: opacity 0.5s;
}
.fade-enter,
.fade-leave-to {
opacity: 0;
}
</style>
了解更多关于 Vue 过渡 的信息。
动机
调用对话框或模态框的常见程序化方法如下:
const dialog = useDialog()
const result = await dialog.open({
title: 'Hello',
content: 'World',
})
这通过将这些信息发送到顶级组件并让它渲染对话框来实现。然而,它 限制了您在 UI 中表达的灵活性。例如,您可能希望标题为红色,或者有额外的按钮等。您最终会得到很多选项,例如:
const result = await dialog.open({
title: 'Hello',
titleClass: 'text-red',
content: 'World',
contentClass: 'text-blue text-sm',
buttons: [
{ text: 'OK', class: 'bg-red', onClick: () => {} },
{ text: 'Cancel', class: 'bg-blue', onClick: () => {} },
],
// ...
})
即使这样也不够灵活。如果您想要更多,您最终可能会使用手动渲染函数:
const result = await dialog.open({
title: 'Hello',
contentSlot: () => h(MyComponent, { content }),
})
这就像在脚本中 重新发明一种新的 DSL 来表达 UI 模板。
因此,此函数允许 在模板而不是脚本中表达 UI(它本应如此),同时仍然能够进行程序化操作。
类型声明
export interface TemplatePromiseProps<Return, Args extends any[] = []> {
/**
* The promise instance.
*/
promise: Promise<Return> | undefined
/**
* Resolve the promise.
*/
resolve: (v: Return | Promise<Return>) => void
/**
* Reject the promise.
*/
reject: (v: any) => void
/**
* Arguments passed to TemplatePromise.start()
*/
args: Args
/**
* Indicates if the promise is resolving.
* When passing another promise to `resolve`, this will be set to `true` until the promise is resolved.
*/
isResolving: boolean
/**
* Options passed to createTemplatePromise()
*/
options: TemplatePromiseOptions
/**
* Unique key for list rendering.
*/
key: number
}
export interface TemplatePromiseOptions {
/**
* Determines if the promise can be called only once at a time.
*
* @default false
*/
singleton?: boolean
/**
* Transition props for the promise.
*/
transition?: TransitionGroupProps
}
export type TemplatePromise<
Return,
Args extends any[] = [],
> = DefineComponent<object> & {
new (): {
$slots: {
default: (_: TemplatePromiseProps<Return, Args>) => any
}
}
} & {
start: (...args: Args) => Promise<Return>
}
/**
* Creates a template promise component.
*
* @see https://vueuse.org/createTemplatePromise
*/
export declare function createTemplatePromise<Return, Args extends any[] = []>(
options?: TemplatePromiseOptions,
): TemplatePromise<Return, Args>