From b98e226ff95170b11e8dfebeeef6a3b2c82fd67b Mon Sep 17 00:00:00 2001 From: ajuner <106791576@qq.com> Date: Fri, 9 Apr 2021 14:48:36 +0800 Subject: [PATCH 1/6] refactor(switch): use composition api --- components/_util/props-util/index.js | 55 ++++---- components/switch/index.tsx | 132 +++++++++--------- components/vc-switch/Switch.jsx | 124 ---------------- components/vc-switch/{index.js => index.ts} | 2 +- .../{PropTypes.js => src/PropTypes.ts} | 2 +- components/vc-switch/src/Switch.tsx | 100 +++++++++++++ 6 files changed, 197 insertions(+), 218 deletions(-) delete mode 100644 components/vc-switch/Switch.jsx rename components/vc-switch/{index.js => index.ts} (57%) rename components/vc-switch/{PropTypes.js => src/PropTypes.ts} (91%) create mode 100644 components/vc-switch/src/Switch.tsx diff --git a/components/_util/props-util/index.js b/components/_util/props-util/index.js index 21a3c10d77..6c2b599dd3 100644 --- a/components/_util/props-util/index.js +++ b/components/_util/props-util/index.js @@ -8,7 +8,7 @@ import isValid from '../isValid'; // return match ? match[1] : ''; // } -const splitAttrs = attrs => { +const splitAttrs = (attrs) => { const allAttrs = Object.keys(attrs); const eventAttrs = {}; const onEvents = {}; @@ -28,7 +28,7 @@ const parseStyleText = (cssText = '', camel) => { const res = {}; const listDelimiter = /;(?![^(]*\))/g; const propertyDelimiter = /:(.+)/; - cssText.split(listDelimiter).forEach(function(item) { + cssText.split(listDelimiter).forEach(function (item) { if (item) { const tmp = item.split(propertyDelimiter); if (tmp.length > 1) { @@ -48,18 +48,18 @@ const slotHasProp = (slot, prop) => { return hasProp(slot, prop); }; -const getScopedSlots = ele => { +const getScopedSlots = (ele) => { return (ele.data && ele.data.scopedSlots) || {}; }; -const getSlots = ele => { +const getSlots = (ele) => { let componentOptions = ele.componentOptions || {}; if (ele.$vnode) { componentOptions = ele.$vnode.componentOptions || {}; } const children = ele.children || componentOptions.children || []; const slots = {}; - children.forEach(child => { + children.forEach((child) => { if (!isEmptyElement(child)) { const name = (child.data && child.data.slot) || 'default'; slots[name] = slots[name] || []; @@ -72,7 +72,7 @@ const getSlots = ele => { const flattenChildren = (children = [], filterEmpty = true) => { const temp = Array.isArray(children) ? children : [children]; const res = []; - temp.forEach(child => { + temp.forEach((child) => { if (Array.isArray(child)) { res.push(...flattenChildren(child, filterEmpty)); } else if (child && child.type === Fragment) { @@ -105,7 +105,7 @@ const getSlot = (self, name = 'default', options = {}) => { } }; -const getAllChildren = ele => { +const getAllChildren = (ele) => { let componentOptions = ele.componentOptions || {}; if (ele.$vnode) { componentOptions = ele.$vnode.componentOptions || {}; @@ -115,18 +115,18 @@ const getAllChildren = ele => { const getSlotOptions = () => { throw Error('使用 .type 直接取值'); }; -const findDOMNode = instance => { +const findDOMNode = (instance) => { let node = instance && (instance.$el || instance); while (node && !node.tagName) { node = node.nextSibling; } return node; }; -const getOptionProps = instance => { +const getOptionProps = (instance) => { const res = {}; if (instance.$ && instance.$.vnode) { const props = instance.$.vnode.props || {}; - Object.keys(instance.$props).forEach(k => { + Object.keys(instance.$props).forEach((k) => { const v = instance.$props[k]; const hyphenateKey = hyphenate(k); if (v !== undefined || hyphenateKey in props) { @@ -136,11 +136,11 @@ const getOptionProps = instance => { } else if (isVNode(instance) && typeof instance.type === 'object') { const originProps = instance.props || {}; const props = {}; - Object.keys(originProps).forEach(key => { + Object.keys(originProps).forEach((key) => { props[camelize(key)] = originProps[key]; }); const options = instance.type.props || {}; - Object.keys(options).forEach(k => { + Object.keys(options).forEach((k) => { const v = resolvePropValue(options, props, k, props[k]); if (v !== undefined || k in props) { res[k] = v; @@ -202,7 +202,7 @@ const getComponentFromProp = (instance, prop, options = instance, execute = true } const slotsProp = []; const componentOptions = instance.componentOptions || {}; - (componentOptions.children || []).forEach(child => { + (componentOptions.children || []).forEach((child) => { if (child.data && child.data.slot === prop) { if (child.data.attrs) { delete child.data.attrs.slot; @@ -218,7 +218,7 @@ const getComponentFromProp = (instance, prop, options = instance, execute = true } }; -const getAllProps = ele => { +const getAllProps = (ele) => { let props = getOptionProps(ele); if (ele.$) { props = { ...props, ...this.$attrs }; @@ -228,17 +228,17 @@ const getAllProps = ele => { return props; }; -const getPropsData = ins => { +const getPropsData = (ins) => { const vnode = ins.$ ? ins.$ : ins; const res = {}; const originProps = vnode.props || {}; const props = {}; - Object.keys(originProps).forEach(key => { + Object.keys(originProps).forEach((key) => { props[camelize(key)] = originProps[key]; }); const options = isPlainObject(vnode.type) ? vnode.type.props : {}; options && - Object.keys(options).forEach(k => { + Object.keys(options).forEach((k) => { const v = resolvePropValue(options, props, k, props[k]); if (k in props) { // 仅包含 props,不包含默认值 @@ -251,7 +251,7 @@ const getValueByProp = (ele, prop) => { return getPropsData(ele)[prop]; }; -const getAttrs = ele => { +const getAttrs = (ele) => { let data = ele.data; if (ele.$vnode) { data = ele.$vnode.data; @@ -259,7 +259,7 @@ const getAttrs = ele => { return data ? data.attrs || {} : {}; }; -const getKey = ele => { +const getKey = (ele) => { let key = ele.key; return key; }; @@ -297,13 +297,13 @@ export function getClass(ele) { let tempCls = props.class || {}; let cls = {}; if (typeof tempCls === 'string') { - tempCls.split(' ').forEach(c => { + tempCls.split(' ').forEach((c) => { cls[c.trim()] = true; }); } else if (Array.isArray(tempCls)) { classNames(tempCls) .split(' ') - .forEach(c => { + .forEach((c) => { cls[c.trim()] = true; }); } else { @@ -319,7 +319,7 @@ export function getStyle(ele, camel) { } else if (camel && style) { // 驼峰化 const res = {}; - Object.keys(style).forEach(k => (res[camelize(k)] = style[k])); + Object.keys(style).forEach((k) => (res[camelize(k)] = style[k])); return res; } return style; @@ -347,7 +347,7 @@ export function isStringElement(c) { export function filterEmpty(children = []) { const res = []; - children.forEach(child => { + children.forEach((child) => { if (Array.isArray(child)) { res.push(...child); } else if (child.type === Fragment) { @@ -356,10 +356,10 @@ export function filterEmpty(children = []) { res.push(child); } }); - return res.filter(c => !isEmptyElement(c)); + return res.filter((c) => !isEmptyElement(c)); } const initDefaultProps = (propTypes, defaultProps) => { - Object.keys(defaultProps).forEach(k => { + Object.keys(defaultProps).forEach((k) => { if (propTypes[k]) { propTypes[k].def && (propTypes[k] = propTypes[k].def(defaultProps[k])); } else { @@ -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, @@ -411,5 +415,6 @@ export { getAllChildren, findDOMNode, flattenChildren, + getPropsSlot, }; export default hasProp; diff --git a/components/switch/index.tsx b/components/switch/index.tsx index 4a388e1eb1..5eb5f77c7f 100644 --- a/components/switch/index.tsx +++ b/components/switch/index.tsx @@ -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>; 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 ? : 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( + 'checked' in props || !('value' in attrs), + 'Switch', + '`value` is not validate prop, do you mean `checked`?', + ); + }); + const { getPrefixCls } = configProvider; + return () => ( - + + ) : 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} + /> ); }, diff --git a/components/vc-switch/Switch.jsx b/components/vc-switch/Switch.jsx deleted file mode 100644 index c3ac8a6f48..0000000000 --- a/components/vc-switch/Switch.jsx +++ /dev/null @@ -1,124 +0,0 @@ -import { switchPropTypes } from './PropTypes'; -import BaseMixin from '../_util/BaseMixin'; -import { hasProp, getOptionProps, getComponent } from '../_util/props-util'; -import Omit from 'omit.js'; -import { defineComponent } from 'vue'; - -// function noop () { -// } -export default defineComponent({ - name: 'VcSwitch', - mixins: [BaseMixin], - inheritAttrs: false, - props: { - ...switchPropTypes, - prefixCls: switchPropTypes.prefixCls.def('rc-switch'), - // onChange: switchPropTypes.onChange.def(noop), - // onClick: switchPropTypes.onClick.def(noop), - }, - data() { - let checked = false; - if (hasProp(this, 'checked')) { - checked = !!this.checked; - } else { - checked = !!this.defaultChecked; - } - return { - stateChecked: checked, - }; - }, - watch: { - checked(val) { - this.stateChecked = val; - }, - }, - mounted() { - this.$nextTick(() => { - const { autofocus, disabled } = this; - if (autofocus && !disabled) { - this.focus(); - } - }); - }, - methods: { - saveRef(c) { - this.refSwitchNode = c; - }, - setChecked(checked, e) { - if (this.disabled) { - return; - } - if (!hasProp(this, 'checked')) { - this.stateChecked = checked; - } - this.__emit('update:checked', checked); - this.__emit('change', checked, e); - }, - handleClick(e) { - const checked = !this.stateChecked; - this.setChecked(checked, e); - this.__emit('click', checked, e); - }, - handleKeyDown(e) { - if (e.keyCode === 37) { - // Left - this.setChecked(false, e); - } else if (e.keyCode === 39) { - // Right - this.setChecked(true, e); - } - }, - handleMouseUp(e) { - this.refSwitchNode?.blur(); - - this.__emit('mouseup', e); - }, - focus() { - this.refSwitchNode?.focus(); - }, - blur() { - this.refSwitchNode?.blur(); - }, - }, - render() { - const { prefixCls, disabled, loadingIcon, ...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 = { - ...Omit(restProps, [ - 'checkedChildren', - 'unCheckedChildren', - 'checked', - 'autofocus', - 'defaultChecked', - ]), - ...$attrs, - onKeydown: this.handleKeyDown, - onClick: this.handleClick, - onMouseup: this.handleMouseUp, - type: 'button', - role: 'switch', - 'aria-checked': checked, - disabled, - class: switchClassName, - ref: this.saveRef, - }; - - return ( - - ); - }, -}); diff --git a/components/vc-switch/index.js b/components/vc-switch/index.ts similarity index 57% rename from components/vc-switch/index.js rename to components/vc-switch/index.ts index bfde65dd6d..dc4db4c328 100644 --- a/components/vc-switch/index.js +++ b/components/vc-switch/index.ts @@ -1,4 +1,4 @@ // base rc-switch 1.9.0 -import Switch from './Switch'; +import Switch from './src/Switch'; export default Switch; diff --git a/components/vc-switch/PropTypes.js b/components/vc-switch/src/PropTypes.ts similarity index 91% rename from components/vc-switch/PropTypes.js rename to components/vc-switch/src/PropTypes.ts index 17bc7ddf91..70ed02ad47 100644 --- a/components/vc-switch/PropTypes.js +++ b/components/vc-switch/src/PropTypes.ts @@ -1,4 +1,4 @@ -import PropTypes from '../_util/vue-types'; +import PropTypes from '../../_util/vue-types'; export const switchPropTypes = { prefixCls: PropTypes.string, diff --git a/components/vc-switch/src/Switch.tsx b/components/vc-switch/src/Switch.tsx new file mode 100644 index 0000000000..4359ff448e --- /dev/null +++ b/components/vc-switch/src/Switch.tsx @@ -0,0 +1,100 @@ +import { switchPropTypes } from './PropTypes'; +import Omit from 'omit.js'; +import { defineComponent, nextTick, onMounted, ref } from 'vue'; +import KeyCode from '../../_util/KeyCode'; + +function getComponent(slots: Record, props: Record, prop: string) { + return slots[prop]?.() ?? props[prop]; +} + +export default defineComponent({ + name: 'VcSwitch', + inheritAttrs: false, + props: { + ...switchPropTypes, + prefixCls: switchPropTypes.prefixCls.def('rc-switch'), + }, + setup(props, { attrs, slots, emit, expose }) { + const checked = ref('checked' in props ? !!props.checked : !!props.defaultChecked); + + const refSwitchNode = ref(); + + onMounted(() => { + nextTick(() => { + if (props.autofocus && !props.disabled) { + refSwitchNode.value.focus(); + } + }); + }); + + const setChecked = (check: boolean, e: MouseEvent | KeyboardEvent) => { + if (props.disabled) { + return; + } + checked.value = !checked.value; + emit('update:checked', checked); + emit('change', check, e); + }; + + const handleClick = (e: MouseEvent) => { + setChecked(checked.value, e); + emit('click', checked.value, e); + }; + + const handleKeyDown = (e: KeyboardEvent) => { + if (e.keyCode === KeyCode.LEFT) { + setChecked(false, e); + } else if (e.keyCode === KeyCode.RIGHT) { + setChecked(true, e); + } + }; + + const handleMouseUp = (e: MouseEvent) => { + refSwitchNode.value?.blur(); + emit('mouseup', e); + }; + + const focus = () => { + refSwitchNode.value?.focus(); + }; + const blur = () => { + refSwitchNode.value?.blur(); + }; + + expose({ focus, blur }); + + return () => ( + + ); + }, +}); From d73521c6271d0b6d489c310963b0a7571f7c6bdf Mon Sep 17 00:00:00 2001 From: ajuner <106791576@qq.com> Date: Fri, 9 Apr 2021 15:24:36 +0800 Subject: [PATCH 2/6] test: fix --- components/_util/props-util/index.js | 50 +++++++++---------- .../__snapshots__/index.test.js.snap | 2 +- components/switch/__tests__/index.test.js | 13 ++++- components/switch/index.tsx | 2 +- 4 files changed, 38 insertions(+), 29 deletions(-) diff --git a/components/_util/props-util/index.js b/components/_util/props-util/index.js index 6c2b599dd3..86eb35642c 100644 --- a/components/_util/props-util/index.js +++ b/components/_util/props-util/index.js @@ -8,7 +8,7 @@ import isValid from '../isValid'; // return match ? match[1] : ''; // } -const splitAttrs = (attrs) => { +const splitAttrs = attrs => { const allAttrs = Object.keys(attrs); const eventAttrs = {}; const onEvents = {}; @@ -28,7 +28,7 @@ const parseStyleText = (cssText = '', camel) => { const res = {}; const listDelimiter = /;(?![^(]*\))/g; const propertyDelimiter = /:(.+)/; - cssText.split(listDelimiter).forEach(function (item) { + cssText.split(listDelimiter).forEach(function(item) { if (item) { const tmp = item.split(propertyDelimiter); if (tmp.length > 1) { @@ -48,18 +48,18 @@ const slotHasProp = (slot, prop) => { return hasProp(slot, prop); }; -const getScopedSlots = (ele) => { +const getScopedSlots = ele => { return (ele.data && ele.data.scopedSlots) || {}; }; -const getSlots = (ele) => { +const getSlots = ele => { let componentOptions = ele.componentOptions || {}; if (ele.$vnode) { componentOptions = ele.$vnode.componentOptions || {}; } const children = ele.children || componentOptions.children || []; const slots = {}; - children.forEach((child) => { + children.forEach(child => { if (!isEmptyElement(child)) { const name = (child.data && child.data.slot) || 'default'; slots[name] = slots[name] || []; @@ -72,7 +72,7 @@ const getSlots = (ele) => { const flattenChildren = (children = [], filterEmpty = true) => { const temp = Array.isArray(children) ? children : [children]; const res = []; - temp.forEach((child) => { + temp.forEach(child => { if (Array.isArray(child)) { res.push(...flattenChildren(child, filterEmpty)); } else if (child && child.type === Fragment) { @@ -105,7 +105,7 @@ const getSlot = (self, name = 'default', options = {}) => { } }; -const getAllChildren = (ele) => { +const getAllChildren = ele => { let componentOptions = ele.componentOptions || {}; if (ele.$vnode) { componentOptions = ele.$vnode.componentOptions || {}; @@ -115,18 +115,18 @@ const getAllChildren = (ele) => { const getSlotOptions = () => { throw Error('使用 .type 直接取值'); }; -const findDOMNode = (instance) => { +const findDOMNode = instance => { let node = instance && (instance.$el || instance); while (node && !node.tagName) { node = node.nextSibling; } return node; }; -const getOptionProps = (instance) => { +const getOptionProps = instance => { const res = {}; if (instance.$ && instance.$.vnode) { const props = instance.$.vnode.props || {}; - Object.keys(instance.$props).forEach((k) => { + Object.keys(instance.$props).forEach(k => { const v = instance.$props[k]; const hyphenateKey = hyphenate(k); if (v !== undefined || hyphenateKey in props) { @@ -136,11 +136,11 @@ const getOptionProps = (instance) => { } else if (isVNode(instance) && typeof instance.type === 'object') { const originProps = instance.props || {}; const props = {}; - Object.keys(originProps).forEach((key) => { + Object.keys(originProps).forEach(key => { props[camelize(key)] = originProps[key]; }); const options = instance.type.props || {}; - Object.keys(options).forEach((k) => { + Object.keys(options).forEach(k => { const v = resolvePropValue(options, props, k, props[k]); if (v !== undefined || k in props) { res[k] = v; @@ -202,7 +202,7 @@ const getComponentFromProp = (instance, prop, options = instance, execute = true } const slotsProp = []; const componentOptions = instance.componentOptions || {}; - (componentOptions.children || []).forEach((child) => { + (componentOptions.children || []).forEach(child => { if (child.data && child.data.slot === prop) { if (child.data.attrs) { delete child.data.attrs.slot; @@ -218,7 +218,7 @@ const getComponentFromProp = (instance, prop, options = instance, execute = true } }; -const getAllProps = (ele) => { +const getAllProps = ele => { let props = getOptionProps(ele); if (ele.$) { props = { ...props, ...this.$attrs }; @@ -228,17 +228,17 @@ const getAllProps = (ele) => { return props; }; -const getPropsData = (ins) => { +const getPropsData = ins => { const vnode = ins.$ ? ins.$ : ins; const res = {}; const originProps = vnode.props || {}; const props = {}; - Object.keys(originProps).forEach((key) => { + Object.keys(originProps).forEach(key => { props[camelize(key)] = originProps[key]; }); const options = isPlainObject(vnode.type) ? vnode.type.props : {}; options && - Object.keys(options).forEach((k) => { + Object.keys(options).forEach(k => { const v = resolvePropValue(options, props, k, props[k]); if (k in props) { // 仅包含 props,不包含默认值 @@ -251,7 +251,7 @@ const getValueByProp = (ele, prop) => { return getPropsData(ele)[prop]; }; -const getAttrs = (ele) => { +const getAttrs = ele => { let data = ele.data; if (ele.$vnode) { data = ele.$vnode.data; @@ -259,7 +259,7 @@ const getAttrs = (ele) => { return data ? data.attrs || {} : {}; }; -const getKey = (ele) => { +const getKey = ele => { let key = ele.key; return key; }; @@ -297,13 +297,13 @@ export function getClass(ele) { let tempCls = props.class || {}; let cls = {}; if (typeof tempCls === 'string') { - tempCls.split(' ').forEach((c) => { + tempCls.split(' ').forEach(c => { cls[c.trim()] = true; }); } else if (Array.isArray(tempCls)) { classNames(tempCls) .split(' ') - .forEach((c) => { + .forEach(c => { cls[c.trim()] = true; }); } else { @@ -319,7 +319,7 @@ export function getStyle(ele, camel) { } else if (camel && style) { // 驼峰化 const res = {}; - Object.keys(style).forEach((k) => (res[camelize(k)] = style[k])); + Object.keys(style).forEach(k => (res[camelize(k)] = style[k])); return res; } return style; @@ -347,7 +347,7 @@ export function isStringElement(c) { export function filterEmpty(children = []) { const res = []; - children.forEach((child) => { + children.forEach(child => { if (Array.isArray(child)) { res.push(...child); } else if (child.type === Fragment) { @@ -356,10 +356,10 @@ export function filterEmpty(children = []) { res.push(child); } }); - return res.filter((c) => !isEmptyElement(c)); + return res.filter(c => !isEmptyElement(c)); } const initDefaultProps = (propTypes, defaultProps) => { - Object.keys(defaultProps).forEach((k) => { + Object.keys(defaultProps).forEach(k => { if (propTypes[k]) { propTypes[k].def && (propTypes[k] = propTypes[k].def(defaultProps[k])); } else { diff --git a/components/switch/__tests__/__snapshots__/index.test.js.snap b/components/switch/__tests__/__snapshots__/index.test.js.snap index 6fa22b0c97..f757570f75 100644 --- a/components/switch/__tests__/__snapshots__/index.test.js.snap +++ b/components/switch/__tests__/__snapshots__/index.test.js.snap @@ -1,7 +1,7 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`Switch should has click wave effect 1`] = ` - `; diff --git a/components/switch/__tests__/index.test.js b/components/switch/__tests__/index.test.js index 810343dc52..8d2ed47aa5 100644 --- a/components/switch/__tests__/index.test.js +++ b/components/switch/__tests__/index.test.js @@ -9,7 +9,11 @@ describe('Switch', () => { mountTest(Switch); it('should has click wave effect', async () => { - const wrapper = mount(Switch); + const wrapper = mount({ + render() { + return ; + }, + }); wrapper.find('.ant-switch').trigger('click'); await new Promise(resolve => setTimeout(resolve, 0)); expect(wrapper.html()).toMatchSnapshot(); @@ -19,7 +23,12 @@ describe('Switch', () => { resetWarned(); const errorSpy = jest.spyOn(console, 'error').mockImplementation(() => {}); - mount(Switch, { props: { value: '' } }); + mount({ + render() { + return ; + }, + }); + console.log(errorSpy); expect(errorSpy).toHaveBeenCalledWith( 'Warning: [antdv: Switch] `value` is not validate prop, do you mean `checked`?', ); diff --git a/components/switch/index.tsx b/components/switch/index.tsx index 5eb5f77c7f..1997efb789 100644 --- a/components/switch/index.tsx +++ b/components/switch/index.tsx @@ -51,7 +51,7 @@ const Switch = defineComponent({ ); } warning( - 'checked' in props || !('value' in attrs), + !('value' in attrs), 'Switch', '`value` is not validate prop, do you mean `checked`?', ); From 3ba157f457855c1e766d911cbacab83cd847310b Mon Sep 17 00:00:00 2001 From: ajuner <106791576@qq.com> Date: Fri, 9 Apr 2021 15:27:52 +0800 Subject: [PATCH 3/6] fix: lint --- components/switch/__tests__/index.test.js | 1 - 1 file changed, 1 deletion(-) diff --git a/components/switch/__tests__/index.test.js b/components/switch/__tests__/index.test.js index 8d2ed47aa5..0742de8e04 100644 --- a/components/switch/__tests__/index.test.js +++ b/components/switch/__tests__/index.test.js @@ -28,7 +28,6 @@ describe('Switch', () => { return ; }, }); - console.log(errorSpy); expect(errorSpy).toHaveBeenCalledWith( 'Warning: [antdv: Switch] `value` is not validate prop, do you mean `checked`?', ); From 7e0868b6c2a88b8721672eb1d4116535205d4556 Mon Sep 17 00:00:00 2001 From: ajuner <106791576@qq.com> Date: Fri, 9 Apr 2021 15:44:35 +0800 Subject: [PATCH 4/6] fix: remove prefixCls --- components/switch/__tests__/__snapshots__/index.test.js.snap | 2 +- components/vc-switch/src/Switch.tsx | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/components/switch/__tests__/__snapshots__/index.test.js.snap b/components/switch/__tests__/__snapshots__/index.test.js.snap index f757570f75..6fa22b0c97 100644 --- a/components/switch/__tests__/__snapshots__/index.test.js.snap +++ b/components/switch/__tests__/__snapshots__/index.test.js.snap @@ -1,7 +1,7 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`Switch should has click wave effect 1`] = ` - `; diff --git a/components/vc-switch/src/Switch.tsx b/components/vc-switch/src/Switch.tsx index 4359ff448e..bc58949cfe 100644 --- a/components/vc-switch/src/Switch.tsx +++ b/components/vc-switch/src/Switch.tsx @@ -66,6 +66,7 @@ export default defineComponent({ return () => ( ); From 7c1c3bf639b930865f9a28a85381443140ad362d Mon Sep 17 00:00:00 2001 From: ajuner <106791576@qq.com> Date: Sat, 10 Apr 2021 21:27:18 +0800 Subject: [PATCH 6/6] fix: use emits --- components/switch/index.tsx | 15 ++++++++------- components/vc-switch/src/Switch.tsx | 1 + 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/components/switch/index.tsx b/components/switch/index.tsx index 1997efb789..d977975178 100644 --- a/components/switch/index.tsx +++ b/components/switch/index.tsx @@ -1,4 +1,4 @@ -import { defineComponent, inject, onBeforeMount, ref, ExtractPropTypes } 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 VcSwitch from '../vc-switch'; @@ -57,25 +57,26 @@ const Switch = defineComponent({ ); }); const { getPrefixCls } = configProvider; + const prefixCls = computed(() => { + return getPrefixCls('switch', props.prefixCls); + }); return () => ( - ) : null + props.loading ? : 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, + [`${prefixCls.value}-small`]: props.size === 'small', + [`${prefixCls.value}-loading`]: props.loading, }} ref={refSwitchNode} /> diff --git a/components/vc-switch/src/Switch.tsx b/components/vc-switch/src/Switch.tsx index 7ee4e9c44c..4064553b83 100644 --- a/components/vc-switch/src/Switch.tsx +++ b/components/vc-switch/src/Switch.tsx @@ -11,6 +11,7 @@ export default defineComponent({ ...switchPropTypes, prefixCls: switchPropTypes.prefixCls.def('rc-switch'), }, + emits: ['update:checked', 'mouseup', 'change', 'click'], setup(props, { attrs, slots, emit, expose }) { const checked = ref('checked' in props ? !!props.checked : !!props.defaultChecked);