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
v-model -> v-model:value
## Switch
v-model -> v-model:checked

View File

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

View File

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

View File

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

View File

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