From 93bde3fb67b427ef986a336f7afdc2783c336216 Mon Sep 17 00:00:00 2001 From: tangjinzhou <415800467@qq.com> Date: Sat, 27 Jun 2020 22:17:48 +0800 Subject: [PATCH] feat: update inputnumber --- antdv-demo | 2 +- components/input-number/index.jsx | 57 +++--- .../vc-input-number/src/InputHandler.js | 12 +- components/vc-input-number/src/index.js | 163 ++++++++++-------- .../vc-m-feedback/src/TouchFeedback.jsx | 77 +++++---- examples/App.vue | 2 +- examples/index.js | 2 + 7 files changed, 174 insertions(+), 141 deletions(-) diff --git a/antdv-demo b/antdv-demo index 6cde2f94c..d68062568 160000 --- a/antdv-demo +++ b/antdv-demo @@ -1 +1 @@ -Subproject commit 6cde2f94ca4a1dbbb260a4436369e2084ff467ed +Subproject commit d680625687a695a9b9a06a131e12f9611a480d5b diff --git a/components/input-number/index.jsx b/components/input-number/index.jsx index 93a4d9a1c..e530697c7 100644 --- a/components/input-number/index.jsx +++ b/components/input-number/index.jsx @@ -1,11 +1,11 @@ +import { inject } from 'vue'; import PropTypes from '../_util/vue-types'; -import { initDefaultProps, getOptionProps, getListeners } from '../_util/props-util'; +import { initDefaultProps, getOptionProps } from '../_util/props-util'; import classNames from 'classnames'; import UpOutlined from '@ant-design/icons-vue/UpOutlined'; import DownOutlined from '@ant-design/icons-vue/DownOutlined'; import VcInputNumber from '../vc-input-number/src'; import { ConfigConsumerProps } from '../config-provider'; -import Base from '../base'; export const InputNumberProps = { prefixCls: PropTypes.string, @@ -29,56 +29,59 @@ export const InputNumberProps = { const InputNumber = { name: 'AInputNumber', - model: { - prop: 'value', - event: 'change', - }, + inheritAttrs: false, props: initDefaultProps(InputNumberProps, { step: 1, }), - inject: { - configProvider: { default: () => ConfigConsumerProps }, + setup() { + return { + configProvider: inject('configProvider', ConfigConsumerProps), + }; }, methods: { + saveInputNumber(inputNumberRef) { + this.inputNumberRef = inputNumberRef; + }, focus() { - this.$refs.inputNumberRef.focus(); + this.inputNumberRef.focus(); }, blur() { - this.$refs.inputNumberRef.blur(); + this.inputNumberRef.blur(); }, }, render() { - const { prefixCls: customizePrefixCls, size, ...others } = getOptionProps(this); + const { prefixCls: customizePrefixCls, size, class: className, ...others } = { + ...getOptionProps(this), + ...this.$attrs, + }; const getPrefixCls = this.configProvider.getPrefixCls; const prefixCls = getPrefixCls('input-number', customizePrefixCls); - const inputNumberClass = classNames({ - [`${prefixCls}-lg`]: size === 'large', - [`${prefixCls}-sm`]: size === 'small', - }); + const inputNumberClass = classNames( + { + [`${prefixCls}-lg`]: size === 'large', + [`${prefixCls}-sm`]: size === 'small', + }, + className, + ); const upIcon = ; const downIcon = ; const vcInputNumberprops = { - props: { - prefixCls, - upHandler: upIcon, - downHandler: downIcon, - ...others, - }, + prefixCls, + upHandler: upIcon, + downHandler: downIcon, + ...others, class: inputNumberClass, - ref: 'inputNumberRef', - on: getListeners(this), }; - return ; + return ; }, }; /* istanbul ignore next */ -InputNumber.install = function(Vue) { - Vue.use(Base); - Vue.component(InputNumber.name, InputNumber); +InputNumber.install = function(app) { + app.component(InputNumber.name, InputNumber); }; export default InputNumber; diff --git a/components/vc-input-number/src/InputHandler.js b/components/vc-input-number/src/InputHandler.js index 75c866752..42b929f5c 100755 --- a/components/vc-input-number/src/InputHandler.js +++ b/components/vc-input-number/src/InputHandler.js @@ -1,9 +1,10 @@ import PropTypes from '../../_util/vue-types'; import Touchable from '../../vc-m-feedback'; -import { getListeners } from '../../_util/props-util'; +import { getSlot } from '../../_util/props-util'; const InputHandler = { name: 'InputHandler', + inheritAttrs: false, props: { prefixCls: PropTypes.string, disabled: PropTypes.bool, @@ -11,15 +12,12 @@ const InputHandler = { render() { const { prefixCls, disabled } = this.$props; const touchableProps = { - props: { - disabled, - activeClassName: `${prefixCls}-handler-active`, - }, - on: getListeners(this), + disabled, + activeClassName: `${prefixCls}-handler-active`, }; return ( - {this.$slots.default} + {getSlot(this)} ); }, diff --git a/components/vc-input-number/src/index.js b/components/vc-input-number/src/index.js index 3a15712d9..02955018f 100755 --- a/components/vc-input-number/src/index.js +++ b/components/vc-input-number/src/index.js @@ -1,7 +1,7 @@ // based on rc-input-number 4.5.5 import PropTypes from '../../_util/vue-types'; import BaseMixin from '../../_util/BaseMixin'; -import { initDefaultProps, hasProp, getOptionProps, getListeners } from '../../_util/props-util'; +import { initDefaultProps, hasProp, getOptionProps } from '../../_util/props-util'; import classNames from 'classnames'; import KeyCode from '../../_util/KeyCode'; import InputHandler from './InputHandler'; @@ -76,15 +76,17 @@ const inputNumberProps = { title: PropTypes.string, name: PropTypes.string, id: PropTypes.string, + type: PropTypes.string, }; export default { name: 'VCInputNumber', mixins: [BaseMixin], - model: { - prop: 'value', - event: 'change', - }, + inheritAttrs: false, + // model: { + // prop: 'value', + // event: 'change', + // }, props: initDefaultProps(inputNumberProps, { focusOnUpDown: true, useTouch: false, @@ -158,6 +160,7 @@ export default { typeof nextValue === 'number' && nextValue > max ) { + this.$emit('update:value', max); this.$emit('change', max); } if ( @@ -166,6 +169,7 @@ export default { typeof nextValue === 'number' && nextValue < min ) { + this.$emit('update:value', min); this.$emit('change', min); } } @@ -179,7 +183,7 @@ export default { }, methods: { updatedFunc() { - const inputElem = this.$refs.inputRef; + const inputElem = this.inputRef; // Restore cursor try { // Firefox set the input cursor after it get focused. @@ -270,7 +274,9 @@ export default { } this.rawInput = this.parser(this.getValueFromEvent(e)); this.setState({ inputValue: this.rawInput }); - this.$emit('change', this.toNumber(this.rawInput)); // valid number or invalid string + const num = this.toNumber(this.rawInput); // valid number or invalid string + this.$emit('update:value', num); + this.$emit('change', num); }, onFocus(...args) { this.setState({ @@ -285,12 +291,12 @@ export default { }); const value = this.getCurrentValidValue(this.inputValue); const newValue = this.setValue(value); - if (this.$listeners.blur) { - const originValue = this.$refs.inputRef.value; + if (this.$attrs.onBlur) { + const originValue = this.inputRef.value; const inputValue = this.getInputDisplayValue({ focused: false, sValue: newValue }); - this.$refs.inputRef.value = inputValue; + this.inputRef.value = inputValue; this.$emit('blur', ...args); - this.$refs.inputRef.value = originValue; + this.inputRef.value = originValue; } }, getCurrentValidValue(value) { @@ -366,6 +372,7 @@ export default { ); } if (changed) { + this.$emit('update:value', newValue); this.$emit('change', newValue); } return newValue; @@ -431,7 +438,7 @@ export default { recordCursorPosition() { // Record position try { - const inputElem = this.$refs.inputRef; + const inputElem = this.inputRef; this.cursorStart = inputElem.selectionStart; this.cursorEnd = inputElem.selectionEnd; this.currentValue = inputElem.value; @@ -444,17 +451,12 @@ export default { } }, fixCaret(start, end) { - if ( - start === undefined || - end === undefined || - !this.$refs.inputRef || - !this.$refs.inputRef.value - ) { + if (start === undefined || end === undefined || !this.inputRef || !this.inputRef.value) { return; } try { - const inputElem = this.$refs.inputRef; + const inputElem = this.inputRef; const currentStart = inputElem.selectionStart; const currentEnd = inputElem.selectionEnd; @@ -470,7 +472,7 @@ export default { restoreByAfter(str) { if (str === undefined) return false; - const fullStr = this.$refs.inputRef.value; + const fullStr = this.inputRef.value; const index = fullStr.lastIndexOf(str); if (index === -1) return false; @@ -504,11 +506,11 @@ export default { }); }, focus() { - this.$refs.inputRef.focus(); + this.inputRef.focus(); this.recordCursorPosition(); }, blur() { - this.$refs.inputRef.blur(); + this.inputRef.blur(); }, formatWrapper(num) { // http://2ality.com/2012/03/signedzero.html @@ -621,8 +623,20 @@ export default { handleInputClick() { this.$emit('click'); }, + saveUp(node) { + this.upHandlerRef = node; + }, + + saveDown(node) { + this.downHandlerRef = node; + }, + + saveInput(node) { + this.inputRef = node; + }, }, render() { + const props = { ...this.$props, ...this.$attrs }; const { prefixCls, disabled, @@ -631,8 +645,10 @@ export default { autoComplete, upHandler, downHandler, - } = this.$props; + class: className, + } = props; const classes = classNames({ + [className]: className, [prefixCls]: true, [`${prefixCls}-disabled`]: disabled, [`${prefixCls}-focused`]: this.focused, @@ -655,6 +671,16 @@ export default { } } + const dataOrAriaAttributeProps = {}; + for (const key in props) { + if ( + props.hasOwnProperty(key) && + (key.substr(0, 5) === 'data-' || key.substr(0, 5) === 'aria-' || key === 'role') + ) { + dataOrAriaAttributeProps[key] = props[key]; + } + } + const editable = !this.readOnly && !this.disabled; // focus state, show input value @@ -665,71 +691,61 @@ export default { let downEvents; if (useTouch) { upEvents = { - touchstart: editable && !upDisabledClass ? this.up : noop, - touchend: this.stop, + onTouchstart: editable && !upDisabledClass ? this.up : noop, + onTouchend: this.stop, }; downEvents = { - touchstart: editable && !downDisabledClass ? this.down : noop, - touchend: this.stop, + onTouchstart: editable && !downDisabledClass ? this.down : noop, + onTouchend: this.stop, }; } else { upEvents = { - mousedown: editable && !upDisabledClass ? this.up : noop, - mouseup: this.stop, - mouseleave: this.stop, + onMousedown: editable && !upDisabledClass ? this.up : noop, + onMouseup: this.stop, + onMouseleave: this.stop, }; downEvents = { - mousedown: editable && !downDisabledClass ? this.down : noop, - mouseup: this.stop, - mouseleave: this.stop, + onMousedown: editable && !downDisabledClass ? this.down : noop, + onMouseup: this.stop, + onMouseleave: this.stop, }; } const isUpDisabled = !!upDisabledClass || disabled || readOnly; const isDownDisabled = !!downDisabledClass || disabled || readOnly; - const { - mouseenter = noop, - mouseleave = noop, - mouseover = noop, - mouseout = noop, - } = getListeners(this); - const contentProps = { - on: { mouseenter, mouseleave, mouseover, mouseout }, - class: classes, - attrs: { title: this.$props.title }, - }; + const upHandlerProps = { - props: { - disabled: isUpDisabled, - prefixCls, - }, - attrs: { - unselectable: 'unselectable', - role: 'button', - 'aria-label': 'Increase Value', - 'aria-disabled': !!isUpDisabled, - }, + disabled: isUpDisabled, + prefixCls, + unselectable: 'unselectable', + role: 'button', + 'aria-label': 'Increase Value', + 'aria-disabled': !!isUpDisabled, class: `${prefixCls}-handler ${prefixCls}-handler-up ${upDisabledClass}`, - on: upEvents, - ref: 'up', + ...upEvents, + ref: this.saveUp, }; const downHandlerProps = { - props: { - disabled: isDownDisabled, - prefixCls, - }, - attrs: { - unselectable: 'unselectable', - role: 'button', - 'aria-label': 'Decrease Value', - 'aria-disabled': !!isDownDisabled, - }, + disabled: isDownDisabled, + prefixCls, + unselectable: 'unselectable', + role: 'button', + 'aria-label': 'Decrease Value', + 'aria-disabled': !!isDownDisabled, class: `${prefixCls}-handler ${prefixCls}-handler-down ${downDisabledClass}`, - on: downEvents, - ref: 'down', + ...downEvents, + ref: this.saveDown, }; - // ref for test + return ( -
+
{upHandler || ( @@ -757,7 +773,7 @@ export default { aria-valuemax={this.max} aria-valuenow={sValue} required={this.required} - type={this.type} + type={props.type} placeholder={this.placeholder} onClick={this.handleInputClick} class={`${prefixCls}-input`} @@ -767,7 +783,7 @@ export default { onBlur={this.onBlur} onKeydown={editable ? this.onKeyDown : noop} onKeyup={editable ? this.onKeyUp : noop} - maxLength={this.maxLength} + maxlength={props.maxLength} readOnly={this.readOnly} disabled={this.disabled} max={this.max} @@ -777,9 +793,10 @@ export default { title={this.title} id={this.id} onInput={this.onChange} - ref="inputRef" + ref={this.saveInput} value={inputDisplayValue} pattern={this.pattern} + {...dataOrAriaAttributeProps} />
diff --git a/components/vc-m-feedback/src/TouchFeedback.jsx b/components/vc-m-feedback/src/TouchFeedback.jsx index cb7f3f2c0..89c388911 100755 --- a/components/vc-m-feedback/src/TouchFeedback.jsx +++ b/components/vc-m-feedback/src/TouchFeedback.jsx @@ -1,4 +1,5 @@ -import { initDefaultProps } from '../../_util/props-util'; +import classNames from 'classnames'; +import { initDefaultProps, getSlot } from '../../_util/props-util'; import { cloneElement } from '../../_util/vnode'; import warning from '../../_util/warning'; import BaseMixin from '../../_util/BaseMixin'; @@ -7,10 +8,12 @@ import { ITouchProps } from './PropTypes'; export default { name: 'TouchFeedback', mixins: [BaseMixin], + inheritAttrs: false, props: initDefaultProps(ITouchProps, { disabled: false, }), data() { + this.child = null; return { active: false, }; @@ -26,8 +29,12 @@ export default { }, methods: { triggerEvent(type, isActive, ev) { - // 暂时仅有input-number用到,事件直接到挂载到Touchable上,不需要像antd那样从子组件触发 - this.$emit(type, ev); + const eventType = `on${type}`; + const { child } = this; + + if (child.props[eventType]) { + child.props[eventType](ev); + } if (isActive !== this.active) { this.setState({ active: isActive, @@ -35,60 +42,66 @@ export default { } }, onTouchStart(e) { - this.triggerEvent('touchstart', true, e); + this.triggerEvent('Touchstart', true, e); }, onTouchMove(e) { - this.triggerEvent('touchmove', false, e); + this.triggerEvent('Touchmove', false, e); }, onTouchEnd(e) { - this.triggerEvent('touchend', false, e); + this.triggerEvent('Touchend', false, e); }, onTouchCancel(e) { - this.triggerEvent('touchcancel', false, e); + this.triggerEvent('Touchcancel', false, e); }, onMouseDown(e) { // pc simulate mobile - this.triggerEvent('mousedown', true, e); + this.triggerEvent('Mousedown', true, e); }, onMouseUp(e) { - this.triggerEvent('mouseup', false, e); + this.triggerEvent('Mouseup', false, e); }, onMouseLeave(e) { - this.triggerEvent('mouseleave', false, e); + this.triggerEvent('Mouseleave', false, e); }, }, render() { const { disabled, activeClassName = '', activeStyle = {} } = this.$props; - const child = this.$slots.default; + let child = getSlot(this); if (child.length !== 1) { warning(false, 'm-feedback组件只能包含一个子元素'); return null; } - let childProps = { - on: disabled - ? {} - : { - touchstart: this.onTouchStart, - touchmove: this.onTouchMove, - touchend: this.onTouchEnd, - touchcancel: this.onTouchCancel, - mousedown: this.onMouseDown, - mouseup: this.onMouseUp, - mouseleave: this.onMouseLeave, - }, - }; + const events = disabled + ? undefined + : { + onTouchstart: this.onTouchStart, + onTouchmove: this.onTouchMove, + onTouchend: this.onTouchEnd, + onTouchcancel: this.onTouchCancel, + onMousedown: this.onMouseDown, + onMouseup: this.onMouseUp, + onMouseleave: this.onMouseLeave, + }; + child = child[0]; + this.child = child; if (!disabled && this.active) { - childProps = { - ...childProps, - ...{ - style: activeStyle, - class: activeClassName, - }, - }; + let { style, class: className } = child.props; + + if (activeStyle !== false) { + if (activeStyle) { + style = { ...style, ...activeStyle }; + } + className = classNames(className, activeClassName); + } + return cloneElement(child, { + class: className, + style, + ...events, + }); } - return cloneElement(child, childProps); + return cloneElement(child, events); }, }; diff --git a/examples/App.vue b/examples/App.vue index 708299153..dc52a4f82 100644 --- a/examples/App.vue +++ b/examples/App.vue @@ -4,7 +4,7 @@