4
4
onBeforeUnmount ,
5
5
onMounted ,
6
6
onUpdated ,
7
+ Ref ,
7
8
ref ,
8
9
Text ,
9
10
watch ,
@@ -19,6 +20,8 @@ import devWarning from '../vc-util/devWarning';
19
20
import type { ButtonType } from './buttonTypes' ;
20
21
import type { VNode } from 'vue' ;
21
22
23
+ type Loading = boolean | number ;
24
+
22
25
const rxTwoCNChar = / ^ [ \u4e00 - \u9fa5 ] { 2 } $ / ;
23
26
const isTwoCNChar = rxTwoCNChar . test . bind ( rxTwoCNChar ) ;
24
27
const props = buttonTypes ( ) ;
@@ -38,18 +41,41 @@ export default defineComponent({
38
41
const { prefixCls, autoInsertSpaceInButton, direction } = useConfigInject ( 'btn' , props ) ;
39
42
40
43
const buttonNodeRef = ref < HTMLElement > ( null ) ;
41
- const delayTimeout = ref ( undefined ) ;
42
- const iconCom = ref < VNode > ( null ) ;
43
- const children = ref < VNode [ ] > ( [ ] ) ;
44
+ const delayTimeoutRef = ref ( undefined ) ;
45
+ let isNeedInserted = false ;
44
46
45
- const sLoading = ref ( props . loading ) ;
47
+ const innerLoading : Ref < Loading > = ref ( false ) ;
46
48
const hasTwoCNChar = ref ( false ) ;
47
49
48
50
const autoInsertSpace = computed ( ( ) => autoInsertSpaceInButton . value !== false ) ;
49
51
50
- const getClasses = ( ) => {
51
- const { type, shape, size, ghost, block, danger } = props ;
52
+ // =============== Update Loading ===============
53
+ const loadingOrDelay = computed ( ( ) =>
54
+ typeof props . loading === 'object' && props . loading . delay
55
+ ? props . loading . delay || true
56
+ : ! ! props . loading ,
57
+ ) ;
52
58
59
+ watch (
60
+ loadingOrDelay ,
61
+ ( val ) => {
62
+ clearTimeout ( delayTimeoutRef . value ) ;
63
+ if ( typeof loadingOrDelay . value === 'number' ) {
64
+ delayTimeoutRef . value = window . setTimeout ( ( ) => {
65
+ innerLoading . value = val ;
66
+ } , loadingOrDelay . value ) ;
67
+ } else {
68
+ innerLoading . value = val ;
69
+ }
70
+ } ,
71
+ {
72
+ immediate : true ,
73
+ } ,
74
+ ) ;
75
+
76
+ const classes = computed ( ( ) => {
77
+ const { type, shape, size, ghost, block, danger } = props ;
78
+ const pre = prefixCls . value ;
53
79
// large => lg
54
80
// small => sm
55
81
let sizeCls = '' ;
@@ -63,22 +89,20 @@ export default defineComponent({
63
89
default :
64
90
break ;
65
91
}
66
- const iconType = sLoading . value ? 'loading' : iconCom . value ;
67
92
return {
68
93
[ attrs . class as string ] : attrs . class ,
69
- [ `${ prefixCls . value } ` ] : true ,
70
- [ `${ prefixCls . value } -${ type } ` ] : type ,
71
- [ `${ prefixCls . value } -${ shape } ` ] : shape ,
72
- [ `${ prefixCls . value } -${ sizeCls } ` ] : sizeCls ,
73
- [ `${ prefixCls . value } -icon-only` ] : children . value . length === 0 && ! ! iconType ,
74
- [ `${ prefixCls . value } -loading` ] : sLoading . value ,
75
- [ `${ prefixCls . value } -background-ghost` ] : ghost && ! isUnborderedButtonType ( type ) ,
76
- [ `${ prefixCls . value } -two-chinese-chars` ] : hasTwoCNChar . value && autoInsertSpace . value ,
77
- [ `${ prefixCls . value } -block` ] : block ,
78
- [ `${ prefixCls . value } -dangerous` ] : ! ! danger ,
79
- [ `${ prefixCls . value } -rtl` ] : direction . value === 'rtl' ,
94
+ [ `${ pre } ` ] : true ,
95
+ [ `${ pre } -${ type } ` ] : type ,
96
+ [ `${ pre } -${ shape } ` ] : shape ,
97
+ [ `${ pre } -${ sizeCls } ` ] : sizeCls ,
98
+ [ `${ pre } -loading` ] : innerLoading . value ,
99
+ [ `${ pre } -background-ghost` ] : ghost && ! isUnborderedButtonType ( type ) ,
100
+ [ `${ pre } -two-chinese-chars` ] : hasTwoCNChar . value && autoInsertSpace . value ,
101
+ [ `${ pre } -block` ] : block ,
102
+ [ `${ pre } -dangerous` ] : ! ! danger ,
103
+ [ `${ pre } -rtl` ] : direction . value === 'rtl' ,
80
104
} ;
81
- } ;
105
+ } ) ;
82
106
83
107
const fixTwoCNChar = ( ) => {
84
108
// Fix for HOC usage like <FormatMessage />
@@ -88,7 +112,7 @@ export default defineComponent({
88
112
}
89
113
const buttonText = node . textContent ;
90
114
91
- if ( isNeedInserted ( ) && isTwoCNChar ( buttonText ) ) {
115
+ if ( isNeedInserted && isTwoCNChar ( buttonText ) ) {
92
116
if ( ! hasTwoCNChar . value ) {
93
117
hasTwoCNChar . value = true ;
94
118
}
@@ -98,7 +122,7 @@ export default defineComponent({
98
122
} ;
99
123
const handleClick = ( event : Event ) => {
100
124
// https://github.com/ant-design/ant-design/issues/30207
101
- if ( sLoading . value || props . disabled ) {
125
+ if ( innerLoading . value || props . disabled ) {
102
126
event . preventDefault ( ) ;
103
127
return ;
104
128
}
@@ -117,9 +141,6 @@ export default defineComponent({
117
141
return child ;
118
142
} ;
119
143
120
- const isNeedInserted = ( ) =>
121
- children . value . length === 1 && ! iconCom . value && ! isUnborderedButtonType ( props . type ) ;
122
-
123
144
watchEffect ( ( ) => {
124
145
devWarning (
125
146
! ( props . ghost && isUnborderedButtonType ( props . type ) ) ,
@@ -128,50 +149,45 @@ export default defineComponent({
128
149
) ;
129
150
} ) ;
130
151
131
- watch (
132
- ( ) => props . loading ,
133
- ( val , preVal ) => {
134
- if ( preVal && typeof preVal !== 'boolean' ) {
135
- clearTimeout ( delayTimeout . value ) ;
136
- }
137
- if ( val && typeof val !== 'boolean' && val . delay ) {
138
- delayTimeout . value = setTimeout ( ( ) => {
139
- sLoading . value = ! ! val ;
140
- } , val . delay ) ;
141
- } else {
142
- sLoading . value = ! ! val ;
143
- }
144
- } ,
145
- {
146
- immediate : true ,
147
- } ,
148
- ) ;
149
-
150
152
onMounted ( fixTwoCNChar ) ;
151
153
onUpdated ( fixTwoCNChar ) ;
152
154
153
155
onBeforeUnmount ( ( ) => {
154
- delayTimeout . value && clearTimeout ( delayTimeout . value ) ;
156
+ delayTimeoutRef . value && clearTimeout ( delayTimeoutRef . value ) ;
155
157
} ) ;
156
158
157
159
return ( ) => {
158
- iconCom . value = getPropsSlot ( slots , props , 'icon' ) ;
159
- children . value = flattenChildren ( getPropsSlot ( slots , props ) ) ;
160
+ const children = flattenChildren ( getPropsSlot ( slots , props ) ) ;
161
+
162
+ const icon = getPropsSlot ( slots , props , 'icon' ) ;
163
+
164
+ isNeedInserted = children . length === 1 && ! icon && ! isUnborderedButtonType ( props . type ) ;
160
165
161
166
const { type, htmlType, disabled, href, title, target } = props ;
162
- const classes = getClasses ( ) ;
163
167
168
+ const iconType = innerLoading . value ? 'loading' : icon ;
164
169
const buttonProps = {
165
170
...attrs ,
166
171
title,
167
172
disabled,
168
- class : classes ,
173
+ class : [
174
+ classes . value ,
175
+ attrs . class ,
176
+ { [ `${ prefixCls . value } -icon-only` ] : children . length === 0 && ! ! iconType } ,
177
+ ] ,
169
178
onClick : handleClick ,
170
179
} ;
171
- const iconNode = sLoading . value ? < LoadingOutlined /> : iconCom . value ;
172
180
173
- const kids = children . value . map ( ( child ) =>
174
- insertSpace ( child , isNeedInserted ( ) && autoInsertSpace . value ) ,
181
+ const iconNode = innerLoading . value ? (
182
+ < span class = { `${ prefixCls . value } -loading-icon` } >
183
+ < LoadingOutlined />
184
+ </ span >
185
+ ) : (
186
+ icon
187
+ ) ;
188
+
189
+ const kids = children . map ( ( child ) =>
190
+ insertSpace ( child , isNeedInserted && autoInsertSpace . value ) ,
175
191
) ;
176
192
177
193
if ( href !== undefined ) {
0 commit comments