feat: update switch (#2439)

* feat: update switch

* fix: avoid bind attrs to root

* test: update switch

* docs: update switch breakchange

* style: remove unused import

Co-authored-by: tangjinzhou <415800467@qq.com>
pull/2494/head
zkwolf 2020-06-23 15:45:30 +08:00 committed by GitHub
parent ae7e792f0a
commit 6f903c3a75
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 74 additions and 59 deletions

View File

@ -59,3 +59,7 @@ v-model -> v-model:checked
checkboxGroup checkboxGroup
v-model -> v-model:value v-model -> v-model:value
## Switch
v-model -> v-model:checked

View File

@ -1,3 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP // Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Switch should has click wave effect 1`] = `<button type="button" role="switch" class="ant-switch ant-switch-checked" aria-checked="true"><span class="ant-switch-inner"></span></button>`; exports[`Switch should has click wave effect 1`] = `
<button class="ant-switch ant-switch-checked" type="button" role="switch" aria-checked="true">
<!----><span class="ant-switch-inner"><!----></span></button>
`;

View File

@ -19,7 +19,7 @@ describe('Switch', () => {
resetWarned(); resetWarned();
const errorSpy = jest.spyOn(console, 'error').mockImplementation(() => {}); const errorSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
mount(Switch, { propsData: { value: '' } }); mount(Switch, { props: { value: '' } });
expect(errorSpy).toHaveBeenCalledWith( expect(errorSpy).toHaveBeenCalledWith(
'Warning: [antdv: Switch] `value` is not validate prop, do you mean `checked`?', 'Warning: [antdv: Switch] `value` is not validate prop, do you mean `checked`?',
); );

View File

@ -1,19 +1,17 @@
import { inject } from 'vue';
import LoadingOutlined from '@ant-design/icons-vue/LoadingOutlined'; import LoadingOutlined from '@ant-design/icons-vue/LoadingOutlined';
import PropTypes from '../_util/vue-types'; import PropTypes from '../_util/vue-types';
import hasProp, { getOptionProps, getComponentFromProp, getListeners } from '../_util/props-util'; import hasProp, { getOptionProps, getComponent } from '../_util/props-util';
import VcSwitch from '../vc-switch'; import VcSwitch from '../vc-switch';
import Wave from '../_util/wave'; import Wave from '../_util/wave';
import { ConfigConsumerProps } from '../config-provider'; import { ConfigConsumerProps } from '../config-provider';
import Base from '../base';
import warning from '../_util/warning'; import warning from '../_util/warning';
import createRefHooks from '../_util/createRefHooks';
const Switch = { const Switch = {
name: 'ASwitch', name: 'ASwitch',
__ANT_SWITCH: true, __ANT_SWITCH: true,
model: { inheritAttrs: false,
prop: 'checked',
event: 'change',
},
props: { props: {
prefixCls: PropTypes.string, prefixCls: PropTypes.string,
// size=default and size=large are the same // size=default and size=large are the same
@ -27,20 +25,25 @@ const Switch = {
autoFocus: PropTypes.bool, autoFocus: PropTypes.bool,
loading: PropTypes.bool, loading: PropTypes.bool,
}, },
inject: { setup() {
configProvider: { default: () => ConfigConsumerProps }, return {
configProvider: inject('configProvider', ConfigConsumerProps),
};
}, },
methods: { methods: {
focus() { focus() {
this.$refs.refSwitchNode.focus(); this.refSwitchNode?.ctx?.focus();
}, },
blur() { blur() {
this.$refs.refSwitchNode.blur(); this.refSwitchNode?.ctx?.blur();
},
saveRef(c) {
this.refSwitchNode = c;
}, },
}, },
created() { created() {
warning( warning(
hasProp(this, 'checked') || !hasProp(this, 'value'), hasProp(this, 'checked') || !('value' in this.$attrs),
'Switch', 'Switch',
'`value` is not validate prop, do you mean `checked`?', '`value` is not validate prop, do you mean `checked`?',
); );
@ -52,27 +55,26 @@ const Switch = {
); );
const getPrefixCls = this.configProvider.getPrefixCls; const getPrefixCls = this.configProvider.getPrefixCls;
const prefixCls = getPrefixCls('switch', customizePrefixCls); const prefixCls = getPrefixCls('switch', customizePrefixCls);
const { $attrs } = this;
const classes = { const classes = {
[$attrs.class]: $attrs.class,
[`${prefixCls}-small`]: size === 'small', [`${prefixCls}-small`]: size === 'small',
[`${prefixCls}-loading`]: loading, [`${prefixCls}-loading`]: loading,
}; };
const loadingIcon = loading ? ( const loadingIcon = loading ? <LoadingOutlined class={`${prefixCls}-loading-icon`} /> : null;
<LoadingOutlined class={`${prefixCls}-loading-icon`} />
) : null;
const switchProps = { const switchProps = {
props: {
...restProps, ...restProps,
prefixCls, prefixCls,
loadingIcon, loadingIcon,
checkedChildren: getComponentFromProp(this, 'checkedChildren'), checkedChildren: getComponent(this, 'checkedChildren'),
unCheckedChildren: getComponentFromProp(this, 'unCheckedChildren'), unCheckedChildren: getComponent(this, 'unCheckedChildren'),
disabled: disabled || loading, disabled: disabled || loading,
}, ...$attrs,
on: getListeners(this),
class: classes, class: classes,
ref: 'refSwitchNode', ...createRefHooks(this.saveRef),
}; };
return ( return (
<Wave insertExtraNode> <Wave insertExtraNode>
<VcSwitch {...switchProps} /> <VcSwitch {...switchProps} />
@ -82,9 +84,8 @@ const Switch = {
}; };
/* istanbul ignore next */ /* istanbul ignore next */
Switch.install = function(Vue) { Switch.install = function(app) {
Vue.use(Base); app.component(Switch.name, Switch);
Vue.component(Switch.name, Switch);
}; };
export default Switch; export default Switch;

View File

@ -9,7 +9,7 @@ export const switchPropTypes = {
// onMouseUp: PropTypes.func, // onMouseUp: PropTypes.func,
// onClick: PropTypes.func, // onClick: PropTypes.func,
tabIndex: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), tabIndex: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
checked: PropTypes.bool.def(false), checked: PropTypes.bool,
defaultChecked: PropTypes.bool.def(false), defaultChecked: PropTypes.bool.def(false),
autoFocus: PropTypes.bool.def(false), autoFocus: PropTypes.bool.def(false),
loadingIcon: PropTypes.any, loadingIcon: PropTypes.any,

View File

@ -1,16 +1,14 @@
import { switchPropTypes } from './PropTypes'; import { switchPropTypes } from './PropTypes';
import BaseMixin from '../_util/BaseMixin'; import BaseMixin from '../_util/BaseMixin';
import { hasProp, getOptionProps, getComponentFromProp, getListeners } from '../_util/props-util'; import { hasProp, getOptionProps, getComponent } from '../_util/props-util';
import createRefHooks from '../_util/createRefHooks';
// function noop () { // function noop () {
// } // }
export default { export default {
name: 'VcSwitch', name: 'VcSwitch',
mixins: [BaseMixin], mixins: [BaseMixin],
model: { inheritAttrs: false,
prop: 'checked',
event: 'change',
},
props: { props: {
...switchPropTypes, ...switchPropTypes,
prefixCls: switchPropTypes.prefixCls.def('rc-switch'), prefixCls: switchPropTypes.prefixCls.def('rc-switch'),
@ -42,6 +40,9 @@ export default {
}); });
}, },
methods: { methods: {
saveRef(c) {
this.refSwitchNode = c;
},
setChecked(checked, e) { setChecked(checked, e) {
if (this.disabled) { if (this.disabled) {
return; return;
@ -50,6 +51,7 @@ export default {
this.stateChecked = checked; this.stateChecked = checked;
} }
this.$emit('change', checked, e); this.$emit('change', checked, e);
this.$emit('update:checked', checked);
}, },
handleClick(e) { handleClick(e) {
const checked = !this.stateChecked; const checked = !this.stateChecked;
@ -66,51 +68,55 @@ export default {
} }
}, },
handleMouseUp(e) { handleMouseUp(e) {
if (this.$refs.refSwitchNode) { this.refSwitchNode?.blur();
this.$refs.refSwitchNode.blur();
}
this.$emit('mouseup', e); this.$emit('mouseup', e);
}, },
focus() { focus() {
this.$refs.refSwitchNode.focus(); this.refSwitchNode?.focus();
}, },
blur() { blur() {
this.$refs.refSwitchNode.blur(); this.refSwitchNode?.blur();
}, },
}, },
render() { render() {
const { prefixCls, disabled, loadingIcon, tabIndex, ...restProps } = getOptionProps(this); const {
prefixCls,
disabled,
loadingIcon,
defaultChecked,
autoFocus,
...restProps
} = getOptionProps(this);
const checked = this.stateChecked; const checked = this.stateChecked;
const { $attrs } = this;
const switchClassName = { const switchClassName = {
[$attrs.class]: $attrs.class,
[prefixCls]: true, [prefixCls]: true,
[`${prefixCls}-checked`]: checked, [`${prefixCls}-checked`]: checked,
[`${prefixCls}-disabled`]: disabled, [`${prefixCls}-disabled`]: disabled,
}; };
const spanProps = { const spanProps = {
props: { ...restProps }, ...restProps,
on: { ...$attrs,
...getListeners(this), onKeydown: this.handleKeyDown,
keydown: this.handleKeyDown, onClick: this.handleClick,
click: this.handleClick, onMouseup: this.handleMouseUp,
mouseup: this.handleMouseUp,
},
attrs: {
type: 'button', type: 'button',
role: 'switch', role: 'switch',
'aria-checked': checked, 'aria-checked': checked,
disabled, disabled,
tabIndex,
},
class: switchClassName, class: switchClassName,
ref: 'refSwitchNode', ...createRefHooks(this.saveRef),
}; };
return ( return (
<button {...spanProps}> <button {...spanProps}>
{loadingIcon} {loadingIcon}
<span class={`${prefixCls}-inner`}> <span class={`${prefixCls}-inner`}>
{checked {checked
? getComponentFromProp(this, 'checkedChildren') ? getComponent(this, 'checkedChildren')
: getComponentFromProp(this, 'unCheckedChildren')} : getComponent(this, 'unCheckedChildren')}
</span> </span>
</button> </button>
); );

View File

@ -35,8 +35,8 @@ import Menu from 'ant-design-vue/menu';
import Mentions from 'ant-design-vue/mentions'; import Mentions from 'ant-design-vue/mentions';
import Dropdown from 'ant-design-vue/dropdown'; import Dropdown from 'ant-design-vue/dropdown';
import Steps from 'ant-design-vue/steps'; import Steps from 'ant-design-vue/steps';
import Switch from 'ant-design-vue/switch';
import Layout from 'ant-design-vue/layout'; import Layout from 'ant-design-vue/layout';
import 'ant-design-vue/style.js'; import 'ant-design-vue/style.js';
const basic = { const basic = {
@ -85,5 +85,6 @@ app
.use(Mentions) .use(Mentions)
.use(Dropdown) .use(Dropdown)
.use(Steps) .use(Steps)
.use(Switch)
.use(Layout) .use(Layout)
.mount('#app'); .mount('#app');