refactor: switch #3885
							parent
							
								
									67b9da71eb
								
							
						
					
					
						commit
						4a7fcf95f5
					
				|  | @ -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 type="button" role="switch" aria-checked="true" class="ant-switch ant-switch-checked"> | ||||
|   <!----><span class="ant-switch-inner"><!----></span> | ||||
| </button> | ||||
| `; | ||||
|  |  | |||
|  | @ -1,7 +1,16 @@ | |||
| import { defineComponent, inject, onBeforeMount, ref, ExtractPropTypes, computed } from 'vue'; | ||||
| import { | ||||
|   defineComponent, | ||||
|   inject, | ||||
|   onBeforeMount, | ||||
|   ref, | ||||
|   ExtractPropTypes, | ||||
|   computed, | ||||
|   onMounted, | ||||
|   nextTick, | ||||
| } from 'vue'; | ||||
| import LoadingOutlined from '@ant-design/icons-vue/LoadingOutlined'; | ||||
| import PropTypes from '../_util/vue-types'; | ||||
| import VcSwitch from '../vc-switch'; | ||||
| import KeyCode from '../_util/KeyCode'; | ||||
| import Wave from '../_util/wave'; | ||||
| import { defaultConfigProvider } from '../config-provider'; | ||||
| import warning from '../_util/warning'; | ||||
|  | @ -18,7 +27,7 @@ const switchProps = { | |||
|   checkedChildren: PropTypes.any, | ||||
|   unCheckedChildren: PropTypes.any, | ||||
|   tabindex: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), | ||||
|   // defaultChecked: PropTypes.looseBool, | ||||
|   defaultChecked: PropTypes.looseBool, | ||||
|   autofocus: PropTypes.looseBool, | ||||
|   loading: PropTypes.looseBool, | ||||
|   checked: PropTypes.looseBool, | ||||
|  | @ -31,10 +40,24 @@ const Switch = defineComponent({ | |||
|   __ANT_SWITCH: true, | ||||
|   inheritAttrs: false, | ||||
|   props: switchProps, | ||||
|   setup(props: SwitchProps, { attrs, slots, expose }) { | ||||
|     const configProvider = inject('configProvider', defaultConfigProvider); | ||||
|     const refSwitchNode = ref(); | ||||
|   emits: ['update:checked', 'mouseup', 'change', 'click', 'keydown'], | ||||
|   setup(props: SwitchProps, { attrs, slots, expose, emit }) { | ||||
|     onBeforeMount(() => { | ||||
|       warning( | ||||
|         !('defaultChecked' in attrs), | ||||
|         'Switch', | ||||
|         `'defaultChecked' is deprecated, please use 'v-model:checked'`, | ||||
|       ); | ||||
|       warning( | ||||
|         !('value' in attrs), | ||||
|         'Switch', | ||||
|         '`value` is not validate prop, do you mean `checked`?', | ||||
|       ); | ||||
|     }); | ||||
| 
 | ||||
|     const configProvider = inject('configProvider', defaultConfigProvider); | ||||
|     const { getPrefixCls } = configProvider; | ||||
|     const refSwitchNode = ref(); | ||||
|     const focus = () => { | ||||
|       refSwitchNode.value?.focus(); | ||||
|     }; | ||||
|  | @ -44,42 +67,85 @@ const Switch = defineComponent({ | |||
| 
 | ||||
|     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); | ||||
|     }); | ||||
|     const checked = computed(() => { | ||||
|       return 'checked' in props ? !!props.checked : !!props.defaultChecked; | ||||
|     }); | ||||
| 
 | ||||
|     onMounted(() => { | ||||
|       nextTick(() => { | ||||
|         if (props.autofocus && !props.disabled) { | ||||
|           refSwitchNode.value.focus(); | ||||
|         } | ||||
|       }); | ||||
|     }); | ||||
| 
 | ||||
|     const setChecked = (check: boolean, e: MouseEvent | KeyboardEvent) => { | ||||
|       if (props.disabled) { | ||||
|         return; | ||||
|       } | ||||
|       emit('update:checked', check); | ||||
|       emit('change', check, e); | ||||
|     }; | ||||
| 
 | ||||
|     const handleClick = (e: MouseEvent) => { | ||||
|       focus(); | ||||
|       const newChecked = !checked.value; | ||||
|       setChecked(newChecked, e); | ||||
|       emit('click', newChecked, e); | ||||
|     }; | ||||
| 
 | ||||
|     const handleKeyDown = (e: KeyboardEvent) => { | ||||
|       if (e.keyCode === KeyCode.LEFT) { | ||||
|         setChecked(false, e); | ||||
|       } else if (e.keyCode === KeyCode.RIGHT) { | ||||
|         setChecked(true, e); | ||||
|       } | ||||
|       emit('keydown', e); | ||||
|     }; | ||||
| 
 | ||||
|     const handleMouseUp = (e: MouseEvent) => { | ||||
|       refSwitchNode.value?.blur(); | ||||
|       emit('mouseup', e); | ||||
|     }; | ||||
|     return () => ( | ||||
|       <Wave insertExtraNode> | ||||
|         <VcSwitch | ||||
|           {...Omit(props, ['prefixCls', 'size', 'loading', 'disabled'])} | ||||
|         <button | ||||
|           {...Omit(props, [ | ||||
|             'prefixCls', | ||||
|             'checkedChildren', | ||||
|             'unCheckedChildren', | ||||
|             'checked', | ||||
|             'autofocus', | ||||
|             'defaultChecked', | ||||
|           ])} | ||||
|           {...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')} | ||||
|           onKeydown={handleKeyDown} | ||||
|           onClick={handleClick} | ||||
|           onMouseup={handleMouseUp} | ||||
|           type="button" | ||||
|           role="switch" | ||||
|           aria-checked={checked.value} | ||||
|           disabled={props.disabled || props.loading} | ||||
|           class={{ | ||||
|             [attrs.class as string]: attrs.class, | ||||
|             [prefixCls.value]: true, | ||||
|             [`${prefixCls.value}-small`]: props.size === 'small', | ||||
|             [`${prefixCls.value}-loading`]: props.loading, | ||||
|             [`${prefixCls.value}-checked`]: checked.value, | ||||
|             [`${prefixCls.value}-disabled`]: props.disabled, | ||||
|           }} | ||||
|           ref={refSwitchNode} | ||||
|         /> | ||||
|         > | ||||
|           {props.loading ? <LoadingOutlined class={`${prefixCls.value}-loading-icon`} /> : null} | ||||
|           <span class={`${prefixCls.value}-inner`}> | ||||
|             {checked.value | ||||
|               ? getPropsSlot(slots, props, 'checkedChildren') | ||||
|               : getPropsSlot(slots, props, 'unCheckedChildren')} | ||||
|           </span> | ||||
|         </button> | ||||
|       </Wave> | ||||
|     ); | ||||
|   }, | ||||
|  |  | |||
|  | @ -1,117 +0,0 @@ | |||
| @switchPrefixCls: rc-switch; | ||||
| 
 | ||||
| @duration: 0.3s; | ||||
| 
 | ||||
| .@{switchPrefixCls} { | ||||
|   position: relative; | ||||
|   display: inline-block; | ||||
|   box-sizing: border-box; | ||||
|   width: 44px; | ||||
|   height: 22px; | ||||
|   line-height: 20px; | ||||
|   padding: 0; | ||||
|   vertical-align: middle; | ||||
|   border-radius: 20px 20px; | ||||
|   border: 1px solid #ccc; | ||||
|   background-color: #ccc; | ||||
|   cursor: pointer; | ||||
|   transition: all @duration cubic-bezier(0.35, 0, 0.25, 1); | ||||
| 
 | ||||
|   &-inner { | ||||
|     color: #fff; | ||||
|     font-size: 12px; | ||||
|     position: absolute; | ||||
|     left: 24px; | ||||
|     top: 0; | ||||
|   } | ||||
| 
 | ||||
|   &:after { | ||||
|     position: absolute; | ||||
|     width: 18px; | ||||
|     height: 18px; | ||||
|     left: 2px; | ||||
|     top: 1px; | ||||
|     border-radius: 50% 50%; | ||||
|     background-color: #fff; | ||||
|     content: ' '; | ||||
|     cursor: pointer; | ||||
|     box-shadow: 0 2px 5px rgba(0, 0, 0, 0.26); | ||||
|     transform: scale(1); | ||||
|     transition: left @duration cubic-bezier(0.35, 0, 0.25, 1); | ||||
|     animation-timing-function: cubic-bezier(0.35, 0, 0.25, 1); | ||||
|     animation-duration: @duration; | ||||
|     animation-name: rcSwitchOff; | ||||
|   } | ||||
| 
 | ||||
|   &:hover:after { | ||||
|     transform: scale(1.1); | ||||
|     animation-name: rcSwitchOn; | ||||
|   } | ||||
| 
 | ||||
|   &:focus { | ||||
|     box-shadow: 0 0 0 2px tint(#2db7f5, 80%); | ||||
|     outline: none; | ||||
|   } | ||||
| 
 | ||||
|   &-checked { | ||||
|     border: 1px solid #87d068; | ||||
|     background-color: #87d068; | ||||
| 
 | ||||
|     .@{switchPrefixCls}-inner { | ||||
|       left: 6px; | ||||
|     } | ||||
| 
 | ||||
|     &:after { | ||||
|       left: 22px; | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   &-disabled { | ||||
|     cursor: no-drop; | ||||
|     background: #ccc; | ||||
|     border-color: #ccc; | ||||
| 
 | ||||
|     &:after { | ||||
|       background: #9e9e9e; | ||||
|       animation-name: none; | ||||
|       cursor: no-drop; | ||||
|     } | ||||
| 
 | ||||
|     &:hover:after { | ||||
|       transform: scale(1); | ||||
|       animation-name: none; | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   &-label { | ||||
|     display: inline-block; | ||||
|     line-height: 20px; | ||||
|     font-size: 14px; | ||||
|     padding-left: 10px; | ||||
|     vertical-align: middle; | ||||
|     white-space: normal; | ||||
|     pointer-events: none; | ||||
|     user-select: text; | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| @keyframes rcSwitchOn { | ||||
|   0% { | ||||
|     transform: scale(1); | ||||
|   } | ||||
|   50% { | ||||
|     transform: scale(1.25); | ||||
|   } | ||||
|   100% { | ||||
|     transform: scale(1.1); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| @keyframes rcSwitchOff { | ||||
|   0% { | ||||
|     transform: scale(1.1); | ||||
|   } | ||||
|   100% { | ||||
|     transform: scale(1); | ||||
|   } | ||||
| } | ||||
|  | @ -1,4 +0,0 @@ | |||
| // base rc-switch 1.9.0
 | ||||
| import Switch from './src/Switch'; | ||||
| 
 | ||||
| export default Switch; | ||||
|  | @ -1,16 +0,0 @@ | |||
| import PropTypes from '../../_util/vue-types'; | ||||
| 
 | ||||
| export const switchPropTypes = { | ||||
|   prefixCls: PropTypes.string, | ||||
|   disabled: PropTypes.looseBool.def(false), | ||||
|   checkedChildren: PropTypes.any, | ||||
|   unCheckedChildren: PropTypes.any, | ||||
|   // onChange: PropTypes.func,
 | ||||
|   // onMouseUp: PropTypes.func,
 | ||||
|   // onClick: PropTypes.func,
 | ||||
|   tabindex: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), | ||||
|   checked: PropTypes.looseBool, | ||||
|   defaultChecked: PropTypes.looseBool.def(false), | ||||
|   autofocus: PropTypes.looseBool.def(false), | ||||
|   loadingIcon: PropTypes.any, | ||||
| }; | ||||
|  | @ -1,99 +0,0 @@ | |||
| import { switchPropTypes } from './PropTypes'; | ||||
| import Omit from 'omit.js'; | ||||
| import { defineComponent, nextTick, onMounted, ref } from 'vue'; | ||||
| import KeyCode from '../../_util/KeyCode'; | ||||
| import { getPropsSlot } from '../../_util/props-util'; | ||||
| 
 | ||||
| export default defineComponent({ | ||||
|   name: 'VcSwitch', | ||||
|   inheritAttrs: false, | ||||
|   props: { | ||||
|     ...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); | ||||
| 
 | ||||
|     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 () => ( | ||||
|       <button | ||||
|         {...Omit(props, [ | ||||
|           'prefixCls', | ||||
|           'checkedChildren', | ||||
|           'unCheckedChildren', | ||||
|           'checked', | ||||
|           'autofocus', | ||||
|           'defaultChecked', | ||||
|         ])} | ||||
|         {...attrs} | ||||
|         onKeydown={handleKeyDown} | ||||
|         onClick={handleClick} | ||||
|         onMouseup={handleMouseUp} | ||||
|         type="button" | ||||
|         role="switch" | ||||
|         aria-checked={checked.value} | ||||
|         disabled={props.disabled} | ||||
|         class={{ | ||||
|           [attrs.class as string]: attrs.class, | ||||
|           [props.prefixCls]: true, | ||||
|           [`${props.prefixCls}-checked`]: checked.value, | ||||
|           [`${props.prefixCls}-disabled`]: props.disabled, | ||||
|         }} | ||||
|         ref={refSwitchNode} | ||||
|       > | ||||
|         {props.loadingIcon} | ||||
|         <span class={`${props.prefixCls}-inner`}> | ||||
|           {checked.value | ||||
|             ? getPropsSlot(slots, props, 'checkedChildren') | ||||
|             : getPropsSlot(slots, props, 'unCheckedChildren')} | ||||
|         </span> | ||||
|       </button> | ||||
|     ); | ||||
|   }, | ||||
| }); | ||||
							
								
								
									
										2
									
								
								v2-doc
								
								
								
								
							
							
								
								
								
								
								
								
							
						
						
									
										2
									
								
								v2-doc
								
								
								
								
							|  | @ -1 +1 @@ | |||
| Subproject commit 496ff9154658d1ff28917f0bea6adfcb0cd05d43 | ||||
| Subproject commit 31d85319dcc0438b3c80957c99f57b931b047c11 | ||||
		Loading…
	
		Reference in New Issue
	
	 tangjinzhou
						tangjinzhou