Skip to content

Commit 7939eb1

Browse files
refactor: spin (#6222)
* fix: typo (#6218) * fix: typo * docs<upload>: docs update * refactor: spin * refactor: spin * refactor: spin * refactor: spinnn * refactor: spin --------- Co-authored-by: lyn <[email protected]>
1 parent 34373ca commit 7939eb1

File tree

7 files changed

+338
-366
lines changed

7 files changed

+338
-366
lines changed

components/spin/Spin.tsx

+94-123
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
import type { VNode, ExtractPropTypes, PropType } from 'vue';
2-
import { inject, cloneVNode, isVNode, defineComponent, nextTick } from 'vue';
2+
import { cloneVNode, isVNode, defineComponent, shallowRef, watch } from 'vue';
33
import debounce from 'lodash-es/debounce';
44
import PropTypes from '../_util/vue-types';
5-
import { getComponent, getSlot } from '../_util/props-util';
5+
import { filterEmpty, getPropsSlot } from '../_util/props-util';
66
import initDefaultProps from '../_util/props-util/initDefaultProps';
7-
import { defaultConfigProvider, configProviderKey } from '../config-provider/context';
7+
import useStyle from './style';
8+
import useConfigInject from '../config-provider/hooks/useConfigInject';
89

910
export type SpinSize = 'small' | 'default' | 'large';
1011
export const spinProps = () => ({
@@ -40,133 +41,103 @@ export default defineComponent({
4041
spinning: true,
4142
wrapperClassName: '',
4243
}),
43-
setup() {
44-
return {
45-
originalUpdateSpinning: null,
46-
configProvider: inject(configProviderKey, defaultConfigProvider),
47-
};
48-
},
49-
data() {
50-
const { spinning, delay } = this;
51-
const shouldBeDelayed = shouldDelay(spinning, delay);
52-
return {
53-
sSpinning: spinning && !shouldBeDelayed,
54-
};
55-
},
56-
created() {
57-
this.originalUpdateSpinning = this.updateSpinning;
58-
this.debouncifyUpdateSpinning(this.$props);
59-
},
60-
mounted() {
61-
this.updateSpinning();
62-
},
63-
updated() {
64-
nextTick(() => {
65-
this.debouncifyUpdateSpinning();
66-
this.updateSpinning();
67-
});
68-
},
69-
beforeUnmount() {
70-
this.cancelExistingSpin();
71-
},
72-
methods: {
73-
debouncifyUpdateSpinning(props?: any) {
74-
const { delay } = props || this.$props;
75-
if (delay) {
76-
this.cancelExistingSpin();
77-
this.updateSpinning = debounce(this.originalUpdateSpinning, delay);
78-
}
79-
},
80-
updateSpinning() {
81-
const { spinning, sSpinning } = this;
82-
if (sSpinning !== spinning) {
83-
this.sSpinning = spinning;
84-
}
85-
},
86-
cancelExistingSpin() {
87-
const { updateSpinning } = this;
88-
if (updateSpinning && (updateSpinning as any).cancel) {
89-
(updateSpinning as any).cancel();
90-
}
91-
},
92-
renderIndicator(prefixCls: string) {
93-
const dotClassName = `${prefixCls}-dot`;
94-
let indicator = getComponent(this, 'indicator');
95-
// should not be render default indicator when indicator value is null
96-
if (indicator === null) {
97-
return null;
44+
setup(props, { attrs, slots }) {
45+
const { prefixCls, size, direction } = useConfigInject('spin', props);
46+
const [wrapSSR, hashId] = useStyle(prefixCls);
47+
const sSpinning = shallowRef(props.spinning && shouldDelay(props.spinning, props.delay));
48+
let updateSpinning: any;
49+
function originalUpdateSpinning() {
50+
if (sSpinning.value !== props.spinning) {
51+
sSpinning.value = props.spinning;
9852
}
99-
if (Array.isArray(indicator)) {
100-
indicator = indicator.length === 1 ? indicator[0] : indicator;
101-
}
102-
if (isVNode(indicator)) {
103-
return cloneVNode(indicator, { class: dotClassName });
53+
}
54+
function cancelExistingSpin() {
55+
if (updateSpinning && updateSpinning.cancel) {
56+
updateSpinning.cancel();
10457
}
105-
106-
if (defaultIndicator && isVNode(defaultIndicator())) {
107-
return cloneVNode(defaultIndicator(), { class: dotClassName });
58+
}
59+
function debouncifyUpdateSpinning() {
60+
const { delay } = props;
61+
if (delay) {
62+
cancelExistingSpin();
63+
updateSpinning = debounce(originalUpdateSpinning, delay);
64+
} else {
65+
updateSpinning = originalUpdateSpinning;
10866
}
109-
110-
return (
111-
<span class={`${dotClassName} ${prefixCls}-dot-spin`}>
112-
<i class={`${prefixCls}-dot-item`} />
113-
<i class={`${prefixCls}-dot-item`} />
114-
<i class={`${prefixCls}-dot-item`} />
115-
<i class={`${prefixCls}-dot-item`} />
116-
</span>
117-
);
118-
},
119-
},
120-
render() {
121-
const {
122-
size,
123-
prefixCls: customizePrefixCls,
124-
tip = this.$slots.tip?.(),
125-
wrapperClassName,
126-
} = this.$props;
127-
const { class: cls, style, ...divProps } = this.$attrs;
128-
const { getPrefixCls, direction } = this.configProvider;
129-
const prefixCls = getPrefixCls('spin', customizePrefixCls);
130-
131-
const { sSpinning } = this;
132-
const spinClassName = {
133-
[prefixCls]: true,
134-
[`${prefixCls}-sm`]: size === 'small',
135-
[`${prefixCls}-lg`]: size === 'large',
136-
[`${prefixCls}-spinning`]: sSpinning,
137-
[`${prefixCls}-show-text`]: !!tip,
138-
[`${prefixCls}-rtl`]: direction === 'rtl',
139-
[cls as string]: !!cls,
140-
};
141-
142-
const spinElement = (
143-
<div
144-
{...divProps}
145-
style={style}
146-
class={spinClassName}
147-
aria-live="polite"
148-
aria-busy={sSpinning}
149-
>
150-
{this.renderIndicator(prefixCls)}
151-
{tip ? <div class={`${prefixCls}-text`}>{tip}</div> : null}
152-
</div>
67+
}
68+
watch(
69+
() => [props.spinning, props.delay],
70+
() => {
71+
debouncifyUpdateSpinning();
72+
updateSpinning?.();
73+
},
74+
{
75+
immediate: true,
76+
},
15377
);
154-
const children = getSlot(this);
155-
if (children && children.length) {
156-
const containerClassName = {
157-
[`${prefixCls}-container`]: true,
158-
[`${prefixCls}-blur`]: sSpinning,
78+
return () => {
79+
const { class: cls, ...divProps } = attrs;
80+
const { tip = slots.tip?.() } = props;
81+
const children = slots.default?.();
82+
const spinClassName = {
83+
[hashId.value]: true,
84+
[prefixCls.value]: true,
85+
[`${prefixCls.value}-sm`]: size.value === 'small',
86+
[`${prefixCls.value}-lg`]: size.value === 'large',
87+
[`${prefixCls.value}-spinning`]: sSpinning.value,
88+
[`${prefixCls.value}-show-text`]: !!tip,
89+
[`${prefixCls.value}-rtl`]: direction.value === 'rtl',
90+
[cls as string]: !!cls,
15991
};
16092

161-
return (
162-
<div class={[`${prefixCls}-nested-loading`, wrapperClassName]}>
163-
{sSpinning && <div key="loading">{spinElement}</div>}
164-
<div class={containerClassName} key="container">
165-
{children}
166-
</div>
93+
function renderIndicator(prefixCls: string) {
94+
const dotClassName = `${prefixCls}-dot`;
95+
let indicator = getPropsSlot(slots, props, 'indicator');
96+
// should not be render default indicator when indicator value is null
97+
if (indicator === null) {
98+
return null;
99+
}
100+
if (Array.isArray(indicator)) {
101+
indicator = indicator.length === 1 ? indicator[0] : indicator;
102+
}
103+
if (isVNode(indicator)) {
104+
return cloneVNode(indicator, { class: dotClassName });
105+
}
106+
107+
if (defaultIndicator && isVNode(defaultIndicator())) {
108+
return cloneVNode(defaultIndicator(), { class: dotClassName });
109+
}
110+
111+
return (
112+
<span class={`${dotClassName} ${prefixCls}-dot-spin`}>
113+
<i class={`${prefixCls}-dot-item`} />
114+
<i class={`${prefixCls}-dot-item`} />
115+
<i class={`${prefixCls}-dot-item`} />
116+
<i class={`${prefixCls}-dot-item`} />
117+
</span>
118+
);
119+
}
120+
const spinElement = (
121+
<div {...divProps} class={spinClassName} aria-live="polite" aria-busy={sSpinning.value}>
122+
{renderIndicator(prefixCls.value)}
123+
{tip ? <div class={`${prefixCls.value}-text`}>{tip}</div> : null}
167124
</div>
168125
);
169-
}
170-
return spinElement;
126+
if (children && filterEmpty(children).length) {
127+
const containerClassName = {
128+
[`${prefixCls.value}-container`]: true,
129+
[`${prefixCls.value}-blur`]: sSpinning.value,
130+
};
131+
return wrapSSR(
132+
<div class={[`${prefixCls.value}-nested-loading`, props.wrapperClassName, hashId.value]}>
133+
{sSpinning.value && <div key="loading">{spinElement}</div>}
134+
<div class={containerClassName} key="container">
135+
{children}
136+
</div>
137+
</div>,
138+
);
139+
}
140+
return wrapSSR(spinElement);
141+
};
171142
},
172143
});

0 commit comments

Comments
 (0)