Skip to content

Commit

Permalink
refactor(switch): use composition api (#3885)
Browse files Browse the repository at this point in the history
* refactor(switch): use composition api

* test: fix

* fix: lint

* fix: remove prefixCls

* fix: use getPropsSlot

* fix: use emits
  • Loading branch information
ajuner authored Apr 11, 2021
1 parent 4c370ed commit 67b9da7
Show file tree
Hide file tree
Showing 7 changed files with 182 additions and 195 deletions.
5 changes: 5 additions & 0 deletions components/_util/props-util/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -389,6 +389,10 @@ function isValidElement(element) {
return element && element.__v_isVNode && typeof element.type !== 'symbol'; // remove text node
}

function getPropsSlot(slots, props, prop = 'default') {
return slots[prop]?.() ?? props[prop];
}

export {
splitAttrs,
hasProp,
Expand All @@ -411,5 +415,6 @@ export {
getAllChildren,
findDOMNode,
flattenChildren,
getPropsSlot,
};
export default hasProp;
12 changes: 10 additions & 2 deletions components/switch/__tests__/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,11 @@ describe('Switch', () => {
mountTest(Switch);

it('should has click wave effect', async () => {
const wrapper = mount(Switch);
const wrapper = mount({
render() {
return <Switch />;
},
});
wrapper.find('.ant-switch').trigger('click');
await new Promise(resolve => setTimeout(resolve, 0));
expect(wrapper.html()).toMatchSnapshot();
Expand All @@ -19,7 +23,11 @@ describe('Switch', () => {
resetWarned();

const errorSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
mount(Switch, { props: { value: '' } });
mount({
render() {
return <Switch value="" />;
},
});
expect(errorSpy).toHaveBeenCalledWith(
'Warning: [antdv: Switch] `value` is not validate prop, do you mean `checked`?',
);
Expand Down
133 changes: 66 additions & 67 deletions components/switch/index.tsx
Original file line number Diff line number Diff line change
@@ -1,86 +1,85 @@
import { defineComponent, inject } from 'vue';
import { defineComponent, inject, onBeforeMount, ref, ExtractPropTypes, computed } from 'vue';
import LoadingOutlined from '@ant-design/icons-vue/LoadingOutlined';
import PropTypes from '../_util/vue-types';
import hasProp, { getOptionProps, getComponent } from '../_util/props-util';
import VcSwitch from '../vc-switch';
import Wave from '../_util/wave';
import { defaultConfigProvider } from '../config-provider';
import warning from '../_util/warning';
import { tuple, withInstall } from '../_util/type';
import { getPropsSlot } from '../_util/props-util';
import Omit from 'omit.js';

export const SwitchSizes = tuple('small', 'default', 'large');

const switchProps = {
prefixCls: PropTypes.string,
size: PropTypes.oneOf(SwitchSizes),
disabled: PropTypes.looseBool,
checkedChildren: PropTypes.any,
unCheckedChildren: PropTypes.any,
tabindex: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
// defaultChecked: PropTypes.looseBool,
autofocus: PropTypes.looseBool,
loading: PropTypes.looseBool,
checked: PropTypes.looseBool,
};

export type SwitchProps = Partial<ExtractPropTypes<typeof switchProps>>;

const Switch = defineComponent({
name: 'ASwitch',
__ANT_SWITCH: true,
inheritAttrs: false,
props: {
prefixCls: PropTypes.string,
// size=default and size=large are the same
size: PropTypes.oneOf(tuple('small', 'default', 'large')),
disabled: PropTypes.looseBool,
checkedChildren: PropTypes.any,
unCheckedChildren: PropTypes.any,
tabindex: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
checked: PropTypes.looseBool,
defaultChecked: PropTypes.looseBool,
autofocus: PropTypes.looseBool,
loading: PropTypes.looseBool,
onChange: PropTypes.func,
onClick: PropTypes.func,
'onUpdate:checked': PropTypes.func,
},
// emits: ['change', 'click', 'update:checked'],
setup() {
return {
refSwitchNode: undefined,
configProvider: inject('configProvider', defaultConfigProvider),
};
},
created() {
warning(
hasProp(this, 'checked') || !('value' in this.$attrs),
'Switch',
'`value` is not validate prop, do you mean `checked`?',
);
},
methods: {
focus() {
this.refSwitchNode?.focus();
},
blur() {
this.refSwitchNode?.blur();
},
saveRef(c) {
this.refSwitchNode = c;
},
},
props: switchProps,
setup(props: SwitchProps, { attrs, slots, expose }) {
const configProvider = inject('configProvider', defaultConfigProvider);
const refSwitchNode = ref();

render() {
const { prefixCls: customizePrefixCls, size, loading, disabled, ...restProps } = getOptionProps(
this,
);
const { getPrefixCls } = this.configProvider;
const prefixCls = getPrefixCls('switch', customizePrefixCls);
const { $attrs } = this;
const classes = {
[$attrs.class as string]: $attrs.class,
[`${prefixCls}-small`]: size === 'small',
[`${prefixCls}-loading`]: loading,
const focus = () => {
refSwitchNode.value?.focus();
};
const loadingIcon = loading ? <LoadingOutlined class={`${prefixCls}-loading-icon`} /> : null;
const switchProps = {
...restProps,
...$attrs,
prefixCls,
loadingIcon,
checkedChildren: getComponent(this, 'checkedChildren'),
unCheckedChildren: getComponent(this, 'unCheckedChildren'),
disabled: disabled || loading,
class: classes,
ref: this.saveRef,
const blur = () => {
refSwitchNode.value?.blur();
};
return (

expose({ focus, blur });

onBeforeMount(() => {
if ('defaultChecked' in attrs) {
console.warn(
`[antdv: Switch]: 'defaultChecked' will be obsolete, please use 'v-model:checked'`,
);
}
warning(
!('value' in attrs),
'Switch',
'`value` is not validate prop, do you mean `checked`?',
);
});
const { getPrefixCls } = configProvider;
const prefixCls = computed(() => {
return getPrefixCls('switch', props.prefixCls);
});
return () => (
<Wave insertExtraNode>
<VcSwitch {...switchProps} />
<VcSwitch
{...Omit(props, ['prefixCls', 'size', 'loading', 'disabled'])}
{...attrs}
checked={props.checked}
prefixCls={prefixCls.value}
loadingIcon={
props.loading ? <LoadingOutlined class={`${prefixCls.value}-loading-icon`} /> : null
}
checkedChildren={getPropsSlot(slots, props, 'checkedChildren')}
unCheckedChildren={getPropsSlot(slots, props, 'unCheckedChildren')}
disabled={props.disabled || props.loading}
class={{
[attrs.class as string]: attrs.class,
[`${prefixCls.value}-small`]: props.size === 'small',
[`${prefixCls.value}-loading`]: props.loading,
}}
ref={refSwitchNode}
/>
</Wave>
);
},
Expand Down
124 changes: 0 additions & 124 deletions components/vc-switch/Switch.jsx

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// base rc-switch 1.9.0
import Switch from './Switch';
import Switch from './src/Switch';

export default Switch;
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import PropTypes from '../_util/vue-types';
import PropTypes from '../../_util/vue-types';

export const switchPropTypes = {
prefixCls: PropTypes.string,
Expand Down
Loading

0 comments on commit 67b9da7

Please sign in to comment.