Skip to content

Commit ee19b48

Browse files
authored
feat(modal): [modal] added the before-close attribute (#4204)
* feat(modal): [modal] added the before-close attribute * fix: modify the comments
1 parent d953756 commit ee19b48

10 files changed

Lines changed: 756 additions & 101 deletions

File tree

examples/sites/demos/apis/modal.js

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,16 @@ export default {
1010
type: 'Function',
1111
defaultValue: '',
1212
desc: {
13-
'zh-CN': '可以配置一个拦截弹窗关闭的方法。如果方法返回 false 值,则拦截弹窗关闭;否则不拦截',
13+
'zh-CN': '设置关闭前的回调函数(仅点击关闭按钮或遮罩区域时被调用),如果回调函数返回 false 则阻止窗口关闭',
1414
'en-US':
15-
'Configure a method to intercept modal closing. If the method returns false, the modal closing is intercepted; otherwise it is not intercepted'
15+
'Set the callback function before closing (only called when clicking the close button or mask area). If the callback function returns false, the modal will not be closed'
1616
},
17-
mode: ['mobile-first'],
18-
mfDemo: ''
17+
mode: ['pc', 'mobile-first'],
18+
mfDemo: '',
19+
pcDemo: 'before-close',
20+
meta: {
21+
stable: '3.31.0'
22+
}
1923
},
2024
{
2125
name: 'cancel-btn-props',
Lines changed: 86 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,70 +1,110 @@
11
<template>
2-
<div class="tiny-demo">
3-
<tiny-radio v-model="value" label="alert" text="alert"></tiny-radio>
4-
<tiny-radio v-model="value" label="confirm" text="confirm"></tiny-radio>
5-
<tiny-radio v-model="value" label="message" text="message"></tiny-radio>
6-
<div style="height: 16px"></div>
7-
<tiny-button @click="handleClick">点击打开 Modal 弹窗</tiny-button>
2+
<div>
3+
<h2>标签式 + 函数调用</h2>
4+
<div class="content">
5+
<tiny-modal
6+
v-model="mainVisible"
7+
:width="600"
8+
:height="300"
9+
:before-close="handleBeforeClose1"
10+
title="Num.1标签式加函数弹窗"
11+
message="NO.1标签式加函数内容"
12+
show-footer
13+
>
14+
</tiny-modal>
15+
<tiny-button @click="mainVisible = true"> 标签式 + 函数式弹窗</tiny-button>
16+
</div>
17+
18+
<h2>点击确认按钮 + 拦截弹窗</h2>
19+
<div class="content">
20+
<tiny-modal
21+
v-model="mainVisible1"
22+
:width="600"
23+
:height="300"
24+
:before-close="handleBeforeClose1"
25+
title="Num.1确认按钮加拦截弹窗"
26+
message="点击确认按钮,出现拦截弹窗"
27+
show-footer
28+
>
29+
<template #footer>
30+
<tiny-button type="primary" @click="onCancelClose1">取消</tiny-button>
31+
<tiny-button style="margin-left: 12px" @click="onConfirmClose1">确定</tiny-button>
32+
</template>
33+
</tiny-modal>
34+
<tiny-button @click="mainVisible1 = true"> 其他</tiny-button>
35+
</div>
836
</div>
937
</template>
1038

1139
<script lang="jsx">
12-
import { TinyRadio, TinyModal, TinyButton } from '@opentiny/vue'
40+
import { Button, Modal } from '@opentiny/vue'
1341
1442
export default {
1543
components: {
16-
TinyRadio,
17-
TinyButton
44+
TinyButton: Button,
45+
TinyModal: Modal
1846
},
1947
data() {
2048
return {
21-
value: 'alert'
49+
mainVisible: false,
50+
mainVisible1: false,
51+
confirmVisible: false,
52+
pendingDone: null
2253
}
2354
},
2455
methods: {
25-
beforeClose(type) {
26-
if (this.value === 'alert') {
27-
/* alert 弹窗有这些关闭类型 close,confirm,esc,mask
28-
这里允许 confirm 关闭 */
29-
return !~['close', 'esc', 'mask'].indexOf(type)
30-
}
56+
handleBeforeClose(type, instance, done) {
57+
this.confirmVisible = true
58+
this.pendingDone = done
59+
return false // 阻止原弹窗立即关闭
60+
},
3161
32-
if (this.value === 'confirm') {
33-
/* confirm 弹窗有这些关闭类型 close,confirm,cancel,esc,mask
34-
这里允许 confirm 或 cancel 关闭 */
35-
return !~['close', 'esc', 'mask'].indexOf(type)
36-
}
62+
onConfirmClose() {
63+
this.confirmVisible = false
64+
this.pendingDone && this.pendingDone() // 调用 done() 关闭原弹窗
65+
this.pendingDone = null
66+
},
3767
38-
if (this.value === 'message') {
39-
/* message 弹窗只有一种关闭类型 show
40-
这里允许 show 关闭 */
41-
return type === 'show'
42-
}
68+
// 点击取消/关闭 -> 只关闭确认弹窗,保留原弹窗
69+
onCancelClose() {
70+
this.confirmVisible = false
71+
this.pendingDone = null // 不调用 done(),原弹窗保持打开
4372
},
44-
handleClick() {
45-
let method
4673
47-
switch (this.value) {
48-
case 'message':
49-
method = TinyModal.message
50-
break
51-
case 'confirm':
52-
method = TinyModal.confirm
53-
break
54-
case 'alert':
55-
method = TinyModal.alert
56-
break
57-
}
74+
handleBeforeClose1(type, instance, done) {
75+
Modal.confirm({
76+
title: '关闭前确认Num.2',
77+
message: '确认弹窗关闭Num.1?',
78+
events: {
79+
confirm: () => done && done(), // 确认 -> 关闭所有弹窗
80+
cancel: () => {} // 取消 -> 保留原弹窗
81+
}
82+
})
83+
return false // 阻止原弹窗立即关闭
84+
},
5885
59-
method({
60-
status: 'info',
61-
title: '普通提示框',
62-
escClosable: true,
63-
maskClosable: true,
64-
beforeClose: this.beforeClose,
65-
message: (h) => [<div>文本信息,文本信息,文本信息</div>]
86+
// 其他
87+
onConfirmClose1() {
88+
// 手动调用 beforeClose,传入关闭回调
89+
this.handleBeforeClose1('confirm', null, () => {
90+
this.mainVisible1 = false
6691
})
92+
},
93+
94+
onCancelClose1() {
95+
this.mainVisible1 = false
6796
}
6897
}
6998
}
7099
</script>
100+
101+
<style scoped>
102+
h2 {
103+
font-size: 16px;
104+
font-weight: bold;
105+
margin: 20px 0 12px;
106+
}
107+
.content {
108+
margin: 8px;
109+
}
110+
</style>

examples/sites/demos/mobile-first/app/modal/webdoc/modal.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -325,8 +325,8 @@ export default {
325325
},
326326
desc: {
327327
'zh-CN':
328-
'<p>通过 `before-close` 属性可以配置一个拦截弹窗关闭的方法。如果方法返回 false 值,则拦截弹窗关闭;否则不拦截<br> 可以通过该拦截方法传入的参数获取关闭的操作类型<br>confirm 弹窗有以下关闭类型:<br> - confirm:点击确认时关闭<br>- cancel:点击取消时关闭<br> - close:点击关闭按钮时关闭<br>- mask: 点击遮罩时关闭<br>- esc:通过按钮 esc 时关闭<br>alert 弹窗比 confirm 弹窗少了 `confirm` 类型<br> message 弹窗只有 `show` 一种关闭类型<p>',
329-
'en-US': '<p>bbutton click</p>'
328+
'<p>通过 `before-close` 属性设置关闭前的回调函数(仅点击关闭按钮或遮罩区域时被调用)。函数入参有type弹窗类型、instance弹窗实例、done回调函数。</p>',
329+
'en-US': ''
330330
},
331331
codeFiles: ['before-close.vue']
332332
}
Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
<template>
2+
<div>
3+
<h2>函数式调用:</h2>
4+
<div class="content">
5+
<tiny-button @click="messageClick"> 函数式弹窗1 </tiny-button>
6+
</div>
7+
8+
<h2>标签式调用</h2>
9+
<div class="content">
10+
<!-- 1:所有关闭操作都触发 beforeClose -->
11+
<tiny-modal
12+
v-model="mainVisible"
13+
:width="600"
14+
:height="300"
15+
:before-close="handleBeforeClose"
16+
title="Num.1标签式弹窗"
17+
message="NO.1标签式内容"
18+
show-footer
19+
>
20+
</tiny-modal>
21+
22+
<!-- 2:关闭前确认弹窗 -->
23+
<tiny-modal
24+
v-model="confirmVisible"
25+
title="Num.2弹窗关闭前确认"
26+
message="NO.2---确定要关闭NO.1窗口吗?未保存的内容将丢失。"
27+
@confirm="onConfirmClose"
28+
@cancel="onCancelClose"
29+
show-footer
30+
>
31+
</tiny-modal>
32+
<tiny-button @click="mainVisible = true"> 标签式弹窗</tiny-button>
33+
</div>
34+
35+
<h2>标签式 + 函数调用</h2>
36+
<div class="content">
37+
<tiny-modal
38+
v-model="mainVisible2"
39+
:width="600"
40+
:height="300"
41+
:before-close="handleBeforeClose1"
42+
title="Num.1标签式加函数弹窗"
43+
message="NO.1标签式加函数内容"
44+
show-footer
45+
>
46+
</tiny-modal>
47+
<tiny-button @click="mainVisible2 = true"> 标签式 + 函数式弹窗</tiny-button>
48+
</div>
49+
50+
<h2>点击确认按钮 + 拦截弹窗</h2>
51+
<div class="content">
52+
<tiny-modal
53+
v-model="mainVisible1"
54+
:width="600"
55+
:height="300"
56+
:before-close="handleBeforeClose1"
57+
title="Num.1确认按钮加拦截弹窗"
58+
message="点击确认按钮,出现拦截弹窗"
59+
show-footer
60+
>
61+
<template #footer>
62+
<tiny-button type="primary" @click="onCancelClose1">取消</tiny-button>
63+
<tiny-button style="margin-left: 12px" @click="onConfirmClose1">确定</tiny-button>
64+
</template>
65+
</tiny-modal>
66+
<tiny-button @click="mainVisible1 = true"> 其他</tiny-button>
67+
</div>
68+
</div>
69+
</template>
70+
71+
<script setup lang="jsx">
72+
import { Button as TinyButton, Modal } from '@opentiny/vue'
73+
import { ref } from 'vue'
74+
75+
const TinyModal = Modal
76+
const mainVisible = ref(false)
77+
const mainVisible1 = ref(false)
78+
const mainVisible2 = ref(false)
79+
const confirmVisible = ref(false)
80+
let pendingDone = null
81+
82+
const handleBeforeClose = (type, instance, done) => {
83+
confirmVisible.value = true
84+
pendingDone = done
85+
return false // 阻止原弹窗立即关闭
86+
}
87+
88+
const onConfirmClose = () => {
89+
confirmVisible.value = false
90+
pendingDone && pendingDone() // 调用 done() 关闭原弹窗
91+
pendingDone = null
92+
}
93+
94+
// 点击取消/关闭 -> 只关闭确认弹窗,保留原弹窗
95+
const onCancelClose = () => {
96+
confirmVisible.value = false
97+
pendingDone = null // 不调用 done(),原弹窗保持打开
98+
}
99+
100+
// 函数式调用:
101+
const messageClick = () => {
102+
Modal.confirm({
103+
message: 'Num.1函数式弹窗内容',
104+
title: '函数式弹窗Num.1',
105+
status: 'warning',
106+
width: '600',
107+
height: '300',
108+
beforeClose: (type, instance, done) => {
109+
Modal.confirm({
110+
title: '关闭前确认Num.2',
111+
message: '确认弹窗关闭Num.1?',
112+
events: {
113+
confirm: () => done && done(), // 确认 -> 关闭所有弹窗
114+
cancel: () => {} // 取消 -> 保留原弹窗
115+
}
116+
})
117+
return false
118+
}
119+
})
120+
}
121+
122+
const handleBeforeClose1 = (type, instance, done) => {
123+
Modal.confirm({
124+
title: '关闭前确认Num.2',
125+
message: '确认弹窗关闭Num.1?',
126+
events: {
127+
confirm: () => done && done(), // 确认 -> 关闭所有弹窗
128+
cancel: () => {} // 取消 -> 保留原弹窗
129+
}
130+
})
131+
return false // 阻止原弹窗立即关闭
132+
}
133+
134+
// 其他
135+
const onConfirmClose1 = () => {
136+
// 手动调用 beforeClose,传入关闭回调
137+
handleBeforeClose1('confirm', null, () => {
138+
mainVisible1.value = false
139+
})
140+
}
141+
142+
const onCancelClose1 = () => {
143+
mainVisible1.value = false
144+
}
145+
</script>
146+
147+
<style scoped>
148+
h2 {
149+
font-size: 16px;
150+
font-weight: bold;
151+
margin: 20px 0 12px;
152+
}
153+
.content {
154+
margin: 8px;
155+
}
156+
</style>

0 commit comments

Comments
 (0)