Skip to content

Commit 67b9da7

Browse files
authored
refactor(switch): use composition api (#3885)
* refactor(switch): use composition api * test: fix * fix: lint * fix: remove prefixCls * fix: use getPropsSlot * fix: use emits
1 parent 4c370ed commit 67b9da7

File tree

7 files changed

+182
-195
lines changed

7 files changed

+182
-195
lines changed

components/_util/props-util/index.js

+5
Original file line numberDiff line numberDiff line change
@@ -389,6 +389,10 @@ function isValidElement(element) {
389389
return element && element.__v_isVNode && typeof element.type !== 'symbol'; // remove text node
390390
}
391391

392+
function getPropsSlot(slots, props, prop = 'default') {
393+
return slots[prop]?.() ?? props[prop];
394+
}
395+
392396
export {
393397
splitAttrs,
394398
hasProp,
@@ -411,5 +415,6 @@ export {
411415
getAllChildren,
412416
findDOMNode,
413417
flattenChildren,
418+
getPropsSlot,
414419
};
415420
export default hasProp;

components/switch/__tests__/index.test.js

+10-2
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,11 @@ describe('Switch', () => {
99
mountTest(Switch);
1010

1111
it('should has click wave effect', async () => {
12-
const wrapper = mount(Switch);
12+
const wrapper = mount({
13+
render() {
14+
return <Switch />;
15+
},
16+
});
1317
wrapper.find('.ant-switch').trigger('click');
1418
await new Promise(resolve => setTimeout(resolve, 0));
1519
expect(wrapper.html()).toMatchSnapshot();
@@ -19,7 +23,11 @@ describe('Switch', () => {
1923
resetWarned();
2024

2125
const errorSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
22-
mount(Switch, { props: { value: '' } });
26+
mount({
27+
render() {
28+
return <Switch value="" />;
29+
},
30+
});
2331
expect(errorSpy).toHaveBeenCalledWith(
2432
'Warning: [antdv: Switch] `value` is not validate prop, do you mean `checked`?',
2533
);

components/switch/index.tsx

+66-67
Original file line numberDiff line numberDiff line change
@@ -1,86 +1,85 @@
1-
import { defineComponent, inject } from 'vue';
1+
import { defineComponent, inject, onBeforeMount, ref, ExtractPropTypes, computed } from 'vue';
22
import LoadingOutlined from '@ant-design/icons-vue/LoadingOutlined';
33
import PropTypes from '../_util/vue-types';
4-
import hasProp, { getOptionProps, getComponent } from '../_util/props-util';
54
import VcSwitch from '../vc-switch';
65
import Wave from '../_util/wave';
76
import { defaultConfigProvider } from '../config-provider';
87
import warning from '../_util/warning';
98
import { tuple, withInstall } from '../_util/type';
9+
import { getPropsSlot } from '../_util/props-util';
10+
import Omit from 'omit.js';
11+
12+
export const SwitchSizes = tuple('small', 'default', 'large');
13+
14+
const switchProps = {
15+
prefixCls: PropTypes.string,
16+
size: PropTypes.oneOf(SwitchSizes),
17+
disabled: PropTypes.looseBool,
18+
checkedChildren: PropTypes.any,
19+
unCheckedChildren: PropTypes.any,
20+
tabindex: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
21+
// defaultChecked: PropTypes.looseBool,
22+
autofocus: PropTypes.looseBool,
23+
loading: PropTypes.looseBool,
24+
checked: PropTypes.looseBool,
25+
};
26+
27+
export type SwitchProps = Partial<ExtractPropTypes<typeof switchProps>>;
1028

1129
const Switch = defineComponent({
1230
name: 'ASwitch',
1331
__ANT_SWITCH: true,
1432
inheritAttrs: false,
15-
props: {
16-
prefixCls: PropTypes.string,
17-
// size=default and size=large are the same
18-
size: PropTypes.oneOf(tuple('small', 'default', 'large')),
19-
disabled: PropTypes.looseBool,
20-
checkedChildren: PropTypes.any,
21-
unCheckedChildren: PropTypes.any,
22-
tabindex: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
23-
checked: PropTypes.looseBool,
24-
defaultChecked: PropTypes.looseBool,
25-
autofocus: PropTypes.looseBool,
26-
loading: PropTypes.looseBool,
27-
onChange: PropTypes.func,
28-
onClick: PropTypes.func,
29-
'onUpdate:checked': PropTypes.func,
30-
},
31-
// emits: ['change', 'click', 'update:checked'],
32-
setup() {
33-
return {
34-
refSwitchNode: undefined,
35-
configProvider: inject('configProvider', defaultConfigProvider),
36-
};
37-
},
38-
created() {
39-
warning(
40-
hasProp(this, 'checked') || !('value' in this.$attrs),
41-
'Switch',
42-
'`value` is not validate prop, do you mean `checked`?',
43-
);
44-
},
45-
methods: {
46-
focus() {
47-
this.refSwitchNode?.focus();
48-
},
49-
blur() {
50-
this.refSwitchNode?.blur();
51-
},
52-
saveRef(c) {
53-
this.refSwitchNode = c;
54-
},
55-
},
33+
props: switchProps,
34+
setup(props: SwitchProps, { attrs, slots, expose }) {
35+
const configProvider = inject('configProvider', defaultConfigProvider);
36+
const refSwitchNode = ref();
5637

57-
render() {
58-
const { prefixCls: customizePrefixCls, size, loading, disabled, ...restProps } = getOptionProps(
59-
this,
60-
);
61-
const { getPrefixCls } = this.configProvider;
62-
const prefixCls = getPrefixCls('switch', customizePrefixCls);
63-
const { $attrs } = this;
64-
const classes = {
65-
[$attrs.class as string]: $attrs.class,
66-
[`${prefixCls}-small`]: size === 'small',
67-
[`${prefixCls}-loading`]: loading,
38+
const focus = () => {
39+
refSwitchNode.value?.focus();
6840
};
69-
const loadingIcon = loading ? <LoadingOutlined class={`${prefixCls}-loading-icon`} /> : null;
70-
const switchProps = {
71-
...restProps,
72-
...$attrs,
73-
prefixCls,
74-
loadingIcon,
75-
checkedChildren: getComponent(this, 'checkedChildren'),
76-
unCheckedChildren: getComponent(this, 'unCheckedChildren'),
77-
disabled: disabled || loading,
78-
class: classes,
79-
ref: this.saveRef,
41+
const blur = () => {
42+
refSwitchNode.value?.blur();
8043
};
81-
return (
44+
45+
expose({ focus, blur });
46+
47+
onBeforeMount(() => {
48+
if ('defaultChecked' in attrs) {
49+
console.warn(
50+
`[antdv: Switch]: 'defaultChecked' will be obsolete, please use 'v-model:checked'`,
51+
);
52+
}
53+
warning(
54+
!('value' in attrs),
55+
'Switch',
56+
'`value` is not validate prop, do you mean `checked`?',
57+
);
58+
});
59+
const { getPrefixCls } = configProvider;
60+
const prefixCls = computed(() => {
61+
return getPrefixCls('switch', props.prefixCls);
62+
});
63+
return () => (
8264
<Wave insertExtraNode>
83-
<VcSwitch {...switchProps} />
65+
<VcSwitch
66+
{...Omit(props, ['prefixCls', 'size', 'loading', 'disabled'])}
67+
{...attrs}
68+
checked={props.checked}
69+
prefixCls={prefixCls.value}
70+
loadingIcon={
71+
props.loading ? <LoadingOutlined class={`${prefixCls.value}-loading-icon`} /> : null
72+
}
73+
checkedChildren={getPropsSlot(slots, props, 'checkedChildren')}
74+
unCheckedChildren={getPropsSlot(slots, props, 'unCheckedChildren')}
75+
disabled={props.disabled || props.loading}
76+
class={{
77+
[attrs.class as string]: attrs.class,
78+
[`${prefixCls.value}-small`]: props.size === 'small',
79+
[`${prefixCls.value}-loading`]: props.loading,
80+
}}
81+
ref={refSwitchNode}
82+
/>
8483
</Wave>
8584
);
8685
},

components/vc-switch/Switch.jsx

-124
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
// base rc-switch 1.9.0
2-
import Switch from './Switch';
2+
import Switch from './src/Switch';
33

44
export default Switch;

components/vc-switch/PropTypes.js renamed to components/vc-switch/src/PropTypes.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import PropTypes from '../_util/vue-types';
1+
import PropTypes from '../../_util/vue-types';
22

33
export const switchPropTypes = {
44
prefixCls: PropTypes.string,

0 commit comments

Comments
 (0)