diff --git a/example/components/demo-block/index.js b/example/components/demo-block/index.js
index e7ea0e740..9872b213a 100644
--- a/example/components/demo-block/index.js
+++ b/example/components/demo-block/index.js
@@ -1,8 +1,9 @@
Component({
properties: {
title: String,
- padding: Boolean
+ padding: Boolean,
+ card: Boolean,
},
- externalClasses: ['custom-class']
+ externalClasses: ['custom-class'],
});
diff --git a/example/components/demo-block/index.wxml b/example/components/demo-block/index.wxml
index 07abe0bf0..d16b9a414 100644
--- a/example/components/demo-block/index.wxml
+++ b/example/components/demo-block/index.wxml
@@ -1,4 +1,7 @@
{{ title }}
-
+
+
+
+
diff --git a/example/components/demo-block/index.wxss b/example/components/demo-block/index.wxss
index 183828c11..9a1d80860 100644
--- a/example/components/demo-block/index.wxss
+++ b/example/components/demo-block/index.wxss
@@ -2,10 +2,15 @@
.demo-block__title {
margin: 0;
+ padding: 20px 15px 15px;
+ color: rgba(69, 90, 100, 0.6);
font-weight: 400;
font-size: 14px;
- color: rgba(69,90,100,.6);
- padding: 20px 15px 15px;
+}
+
+.demo-block__card {
+ overflow: hidden;
+ border-radius: 8px;
}
.demo-block--padding {
diff --git a/example/pages/dialog/index.js b/example/pages/dialog/index.js
index 875defb52..40f45eb97 100644
--- a/example/pages/dialog/index.js
+++ b/example/pages/dialog/index.js
@@ -52,19 +52,23 @@ Page({
},
onClickAsyncClose() {
- Dialog.confirm({
- title: '标题',
- message,
- asyncClose: true,
- })
- .then(() => {
+ const beforeClose = (action) =>
+ new Promise((resolve) => {
setTimeout(() => {
- Dialog.close();
+ if (action === 'confirm') {
+ resolve(true);
+ } else {
+ // 拦截取消操作
+ resolve(false);
+ }
}, 1000);
- })
- .catch(() => {
- Dialog.close();
});
+
+ Dialog.confirm({
+ title: '标题',
+ message,
+ beforeClose,
+ });
},
onClose() {
diff --git a/example/pages/dialog/index.wxml b/example/pages/dialog/index.wxml
index beb07d006..14442bf90 100644
--- a/example/pages/dialog/index.wxml
+++ b/example/pages/dialog/index.wxml
@@ -1,51 +1,35 @@
-
-
- 提示弹窗
-
-
- 提示弹窗(无标题)
-
+
+
+
+
-
-
- 提示弹窗
-
-
- 提示弹窗(无标题)
-
+
+
+
-
-
- 确认弹窗
-
+
+
-
-
- 异步关闭
-
+
+
-
-
- 组件调用
-
-
-
-
-
+
+
+
diff --git a/packages/common/utils.ts b/packages/common/utils.ts
index 633088dbe..954f41f01 100644
--- a/packages/common/utils.ts
+++ b/packages/common/utils.ts
@@ -1,4 +1,4 @@
-import { isNumber, isPlainObject } from './validator';
+import { isNumber, isPlainObject, isPromise } from './validator';
export function isDef(value: any): boolean {
return value !== undefined && value !== null;
@@ -96,3 +96,11 @@ export function getAllRect(
}
);
}
+
+export function toPromise(promiseLike: Promise | unknown) {
+ if (isPromise(promiseLike)) {
+ return promiseLike;
+ }
+
+ return Promise.resolve(promiseLike);
+}
diff --git a/packages/dialog/README.md b/packages/dialog/README.md
index e42bce50b..89ec90429 100644
--- a/packages/dialog/README.md
+++ b/packages/dialog/README.md
@@ -43,9 +43,26 @@ Dialog.alert({
});
```
-### 圆角样式
+### 消息确认
+
+用于确认消息,包含取消和确认按钮
+
+```javascript
+Dialog.confirm({
+ title: '标题',
+ message: '弹窗内容',
+})
+ .then(() => {
+ // on confirm
+ })
+ .catch(() => {
+ // on cancel
+ });
+```
+
+### 圆角按钮风格
-样式为圆角风格。
+将 theme 选项设置为 `round-button` 可以展示圆角按钮风格的弹窗。
```html
@@ -70,46 +87,32 @@ Dialog.alert({
});
```
-### 消息确认
-
-用于确认消息,包含取消和确认按钮
-
-```javascript
-Dialog.confirm({
- title: '标题',
- message: '弹窗内容',
-})
- .then(() => {
- // on confirm
- })
- .catch(() => {
- // on cancel
- });
-```
-
### 异步关闭
-设置`asyncClose`属性开启异步关闭,开启后可以手动调用`Dialog.close`方法关闭弹窗
+通过 `beforeClose` 属性可以传入一个回调函数,在弹窗关闭前进行特定操作。
```javascript
+const beforeClose = (action) => new Promise((resolve) => {
+ setTimeout(() => {
+ if (action === 'confirm') {
+ resolve(true);
+ } else {
+ // 拦截取消操作
+ resolve(false);
+ }
+ }, 1000);
+});
+
Dialog.confirm({
title: '标题',
message: '弹窗内容'
- asyncClose: true
-})
- .then(() => {
- setTimeout(() => {
- Dialog.close();
- }, 1000);
- })
- .catch(() => {
- Dialog.close();
- });
+ beforeClose
+});
```
### 组件调用
-通过组件调用 Dialog 时,可以实现自定义弹窗内容、监听微信开放能力回调事件等功能,具体参考下例
+如果需要在弹窗内嵌入组件或其他自定义内容,可以使用组件调用的方式。
```html
boolean \| Promise_ | - |
+| context | 选择器的选择范围,可以传入自定义组件的 this 作为上下文 | _object_ | 当前页面 |
+| transition | 动画名称,可选值为`fade` `none` | _string_ | `scale` |
+| confirmButtonOpenType | 确认按钮的微信开放能力,具体支持可参考 [微信官方文档](https://mp.weixin.qq.com/debug/wxadoc/dev/component/button.html) | _string_ | - |
### OpenType Options
@@ -205,7 +209,7 @@ Page({
| --- | --- | --- | --- |
| show | 是否显示弹窗 | _boolean_ | - |
| title | 标题 | _string_ | - |
-| width | 弹窗宽度,默认单位为`px` | _string \| number_ | `320px` | 1.0.0 |
+| width | 弹窗宽度,默认单位为`px` | _string \| number_ | `320px` |
| message | 文本内容,支持通过`\n`换行 | _string_ | - |
| theme | 样式风格,可选值为`round-button` | _string_ | `default` |
| message-align | 内容对齐方式,可选值为`left` `right` | _string_ | `center` |
@@ -223,7 +227,8 @@ Page({
| close-on-click-overlay | 点击遮罩层时是否关闭弹窗 | _boolean_ | `false` |
| use-slot | 是否使用自定义内容的插槽 | _boolean_ | `false` |
| use-title-slot | 是否使用自定义标题的插槽 | _boolean_ | `false` |
-| async-close | 是否异步关闭弹窗,开启后需要手动控制弹窗的关闭 | _boolean_ | `false` |
+| async-close | 已废弃,将在 2.0.0 移除,请使用 `beforeClose` 属性代替 | _boolean_ | `false` |
+| before-close | 关闭前的回调函数,返回 `false` 可阻止关闭,支持返回 Promise | _(action) => boolean \| Promise_ | - |
| transition | 动画名称,可选值为`fade` | _string_ | `scale` |
| confirm-button-open-type | 确认按钮的微信开放能力,具体支持可参考 [微信官方文档](https://mp.weixin.qq.com/debug/wxadoc/dev/component/button.html) | _string_ | - |
diff --git a/packages/dialog/dialog.ts b/packages/dialog/dialog.ts
index 5dd27f8c6..ff9d21ef4 100644
--- a/packages/dialog/dialog.ts
+++ b/packages/dialog/dialog.ts
@@ -1,4 +1,5 @@
let queue: WechatMiniprogram.Component.TrivialInstance[] = [];
+export type Action = 'confirm' | 'cancel' | 'overlay';
interface DialogOptions {
lang?: string;
@@ -17,7 +18,11 @@ interface DialogOptions {
className?: string;
customStyle?: string;
transition?: string;
+ /**
+ * @deprecated use beforeClose instead
+ */
asyncClose?: boolean;
+ beforeClose?: null | (() => Promise | void);
businessId?: number;
sessionFrom?: string;
overlayStyle?: string;
@@ -46,6 +51,7 @@ const defaultOptions: DialogOptions = {
selector: '#van-dialog',
className: '',
asyncClose: false,
+ beforeClose: null,
transition: 'scale',
customStyle: '',
messageAlign: '',
@@ -81,8 +87,12 @@ const Dialog = (options: DialogOptions) => {
if (dialog) {
dialog.setData({
- onCancel: reject,
- onConfirm: resolve,
+ callback: (
+ action: Action,
+ instance: WechatMiniprogram.Component.TrivialInstance
+ ) => {
+ action === 'confirm' ? resolve(instance) : reject(instance);
+ },
...options,
});
diff --git a/packages/dialog/index.ts b/packages/dialog/index.ts
index ea53003d1..bd27755d5 100644
--- a/packages/dialog/index.ts
+++ b/packages/dialog/index.ts
@@ -2,8 +2,8 @@ import { VantComponent } from '../common/component';
import { button } from '../mixins/button';
import { openType } from '../mixins/open-type';
import { GRAY, RED } from '../common/color';
-
-type Action = 'confirm' | 'cancel' | 'overlay';
+import { toPromise } from '../common/utils';
+import type { Action } from './dialog';
VantComponent({
mixins: [button, openType],
@@ -26,6 +26,7 @@ VantComponent({
customStyle: String,
asyncClose: Boolean,
messageAlign: String,
+ beforeClose: null,
overlayStyle: String,
useTitleSlot: Boolean,
showCancelButton: Boolean,
@@ -86,19 +87,16 @@ VantComponent({
this.onClose('overlay');
},
- handleAction(action: Action) {
- if (this.data.asyncClose) {
- this.setData({
- [`loading.${action}`]: true,
- });
- }
+ close(action) {
+ this.setData({ show: false });
- this.onClose(action);
- },
+ wx.nextTick(() => {
+ this.$emit('close', action);
- close() {
- this.setData({
- show: false,
+ const { callback } = this.data;
+ if (callback) {
+ callback(action, this);
+ }
});
},
@@ -111,20 +109,27 @@ VantComponent({
});
},
- onClose(action: Action) {
- if (!this.data.asyncClose) {
- this.close();
+ handleAction(action: Action) {
+ this.$emit(action, { dialog: this });
+
+ const { asyncClose, beforeClose } = this.data;
+ if (!asyncClose && !beforeClose) {
+ this.close(action);
+ return;
}
- this.$emit('close', action);
- // 把 dialog 实例传递出去,可以通过 stopLoading() 在外部关闭按钮的 loading
- this.$emit(action, { dialog: this });
+ this.setData({
+ [`loading.${action}`]: true,
+ });
- const callback = this.data[
- action === 'confirm' ? 'onConfirm' : 'onCancel'
- ];
- if (callback) {
- callback(this);
+ if (beforeClose) {
+ toPromise(beforeClose(action)).then((value) => {
+ if (value) {
+ this.close(action);
+ } else {
+ this.stopLoading();
+ }
+ });
}
},
},