Skip to content

refactor(switch): use composition api #3885

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Apr 11, 2021
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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;
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`Switch should has click wave effect 1`] = `
<button class="ant-switch ant-switch-checked" type="button" role="switch" aria-checked="true">
<button prefixcls="ant-switch" class="ant-switch ant-switch-checked" type="button" role="switch" aria-checked="true">
<!----><span class="ant-switch-inner"><!----></span>
</button>
`;
13 changes: 11 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,12 @@ describe('Switch', () => {
resetWarned();

const errorSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
mount(Switch, { props: { value: '' } });
mount({
render() {
return <Switch value="" />;
},
});
console.log(errorSpy);
expect(errorSpy).toHaveBeenCalledWith(
'Warning: [antdv: Switch] `value` is not validate prop, do you mean `checked`?',
);
Expand Down
132 changes: 65 additions & 67 deletions components/switch/index.tsx
Original file line number Diff line number Diff line change
@@ -1,86 +1,84 @@
import { defineComponent, inject } from 'vue';
import { defineComponent, inject, onBeforeMount, ref, ExtractPropTypes } 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;
return () => (
<Wave insertExtraNode>
<VcSwitch {...switchProps} />
<VcSwitch
{...Omit(props, ['prefixCls', 'size', 'loading', 'disabled'])}
{...attrs}
checked={props.checked}
prefixCls={getPrefixCls('switch', props.prefixCls)}
loadingIcon={
props.loading ? (
<LoadingOutlined class={`${getPrefixCls('switch', props.prefixCls)}-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,
[`${getPrefixCls('switch', props.prefixCls)}-small`]: props.size === 'small',
[`${getPrefixCls('switch', props.prefixCls)}-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