Skip to content

createTemplatePromise

类别
导出体积
390 B
上次更改
2 months ago

将模板作为 Promise。适用于构建自定义对话框、模态框、提示框等。

示例

使用方法

vue
<script setup lang="ts">
import { 
createTemplatePromise
} from '@vueuse/core'
const
TemplatePromise
=
createTemplatePromise
()
async function
open
() {
const
result
= await
TemplatePromise
.
start
()
// 按钮被点击后,result 为 'ok' } </script> <template> <
TemplatePromise
v-slot
="{
promise
,
resolve
,
reject
,
args
}">
<!-- 你的 UI --> <
button
@
click
="
resolve
('ok')">
确定 </
button
>
</TemplatePromise> </template>

特性

  • 编程式调用 - 将你的 UI 作为 Promise 调用
  • 模板 - 使用 Vue 模板进行渲染,而不是新的 DSL
  • TypeScript - 通过泛型类型实现完整的类型安全性
  • 无渲染 - 你完全控制 UI
  • 过渡 - 使用支持的 Vue 过渡

此功能是从 vue-template-promise 迁移而来。

使用方法

createTemplatePromise 返回一个 Vue 组件,你可以直接在模板中使用 <script setup>

ts
import { 
createTemplatePromise
} from '@vueuse/core'
const
TemplatePromise
=
createTemplatePromise
()
const
MyPromise
=
createTemplatePromise
<boolean>() // 使用泛型类型
js
import { createTemplatePromise } from '@vueuse/core'
const TemplatePromise = createTemplatePromise()
const MyPromise = createTemplatePromise() // 使用泛型类型

在模板中,使用 v-slot 来访问 Promise 和 resolve 函数。

vue
<template>
  <TemplatePromise v-slot="{ 
promise
,
resolve
,
reject
,
args
}">
<!-- 你可以放置任何内容 --> <
button
@
click
="
resolve
('ok')">
确定 </
button
>
</TemplatePromise> <MyPromise v-slot="{
promise
,
resolve
,
reject
,
args
}">
<!-- 另一个示例 --> </MyPromise> </template>

插槽最初不会被渲染 (类似于 v-if="false"),直到你从组件中调用 start 方法。

ts
const 
result
= await
TemplatePromise
.
start
()

一旦在模板中调用了 resolvereject,Promise 将被解决或拒绝,并返回你传递的值。一旦解决,插槽将自动移除。

传递参数

你可以通过参数将参数传递给 start

ts
import { 
createTemplatePromise
} from '@vueuse/core'
const
TemplatePromise
=
createTemplatePromise
<boolean, [string, number]>()
js
import { createTemplatePromise } from '@vueuse/core'
const TemplatePromise = createTemplatePromise()
ts
const 
result
= await
TemplatePromise
.
start
('hello', 123) // Pr

在模板插槽中,你可以通过 args 属性访问参数。

vue
<template>
  <TemplatePromise v-slot="{ 
args
,
resolve
}">
<
div
>{{
args
[0] }}</
div
>
<!-- hello --> <
div
>{{
args
[1] }}</
div
>
<!-- 123 --> <
button
@
click
="
resolve
(true)">
确定 </
button
>
</TemplatePromise> </template>

过渡

你可以使用过渡来为插槽添加动画效果。

vue
<script setup lang="ts">
const 
TemplatePromise
= createTemplatePromise<
ReturnType
>({
transition
: {
name
: 'fade',
appear
: true,
}, }) </script> <template> <
TemplatePromise
v-slot="{
resolve
}">
<!-- 你的 UI --> <
button
@
click
="
resolve
('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 过渡

动机

以编程方式调用对话框或模型的常见方法如下:

ts
const 
dialog
= useDialog()
const
result
= await
dialog
.open({
title
: 'Hello',
content
: 'World',
})

通过将这些信息发送到顶层组件并让其渲染对话框,这种方法可以工作。然而,它限制了你可以在 UI 中表达的灵活性。例如,你可能希望标题是红色的,或者有额外的按钮等。你可能会得到很多选项,如:

ts
const 
result
= await dialog.open({
title
: 'Hello',
titleClass
: 'text-red',
content
: 'World',
contentClass
: 'text-blue text-sm',
buttons
: [
{
text
: '确定',
class
: 'bg-red',
onClick
: () => {} },
{
text
: '取消',
class
: 'bg-blue',
onClick
: () => {} },
], // ... })

即使这样也不够灵活。如果你想要更多,你可能最终会得到手动渲染函数。

ts
const 
result
= await dialog.open({
title
: 'Hello',
contentSlot
: () =>
h
(MyComponent, {
content
}),
})

这就像在脚本中重新发明一个新的 DSL 来表达 UI 模板。

因此,这个函数允许在模板中表达 UI 而不是脚本,这是它应该在的地方,同时仍然能够以编程方式进行操作。

类型声明

显示类型声明
ts
export interface 
TemplatePromiseProps
<
Return
,
Args
extends any[] = []> {
/** * Promise 实例。 */
promise
:
Promise
<
Return
> | undefined
/** * 解决(完成)promise。 */
resolve
: (
v
:
Return
|
Promise
<
Return
>) => void
/** * 拒绝(失败)promise。 */
reject
: (
v
: any) => void
/** * 传递给 TemplatePromise.start() 的参数。 */
args
:
Args
/** * 表示 promise 是否正在解决中。 * 当向 `resolve` 传递另一个 promise 时,这将被设置为 `true` 直到该 promise 被解决。 */
isResolving
: boolean
/** * 传递给 createTemplatePromise() 的选项。 */
options
: TemplatePromiseOptions
/** * 用于列表渲染的唯一键。 */
key
: number
} export interface TemplatePromiseOptions { /** * 决定 promise 是否只能一次调用一次。 * * @default false 默认为 false */
singleton
?: boolean
/** * promise 的过渡属性。 */
transition
?:
TransitionGroupProps
} export type
TemplatePromise
<
Return
,
Args
extends any[] = [],
> =
DefineComponent
<object> & {
new (): {
$slots
: {
default
: (
_
:
TemplatePromiseProps
<
Return
,
Args
>) => any
} } } & {
start
: (...
args
:
Args
) =>
Promise
<
Return
>
} /** * 将模板作为 Promise。适用于构建自定义对话框、模态框、提示框等。 * * @see https://vueuse.org/createTemplatePromise * * @__NO_SIDE_EFFECTS__ */ export declare function
createTemplatePromise
<
Return
,
Args
extends any[] = []>(
options
?: TemplatePromiseOptions,
):
TemplatePromise
<
Return
,
Args
>

源码

源码演示文档

贡献者

一纸忘忧
Anthony Fu
Anthony Fu
SerKo
Robin
David Gonzalez
ethmcc
Aaron-zon
Haoqun Jiang
Bruce

更新日志

d32f8 - refactor: add @__NO_SIDE_EFFECTS__ annotations to all pure functions (#4907)
0a9ed - feat!: drop Vue 2 support, optimize bundles and clean up (#4349)
a086e - fix: stricter types