feat: update input

pull/2502/head
tangjinzhou 2020-06-27 14:02:30 +08:00
parent e00637f76c
commit 69f7573fe5
14 changed files with 252 additions and 250 deletions

@ -1 +1 @@
Subproject commit c2e13cef53abb73e36ad7e506a9a03f1268fc3e8
Subproject commit 6cde2f94ca4a1dbbb260a4436369e2084ff467ed

View File

@ -73,3 +73,7 @@ renderTabBar({props, on, style, class}, DefaultTabBar) -> {DefaultTabBar, ...pro
## card
tabList[{scopedSlots}] -> tabList[{slots}]
## rate
v-model -> v-model:value

View File

@ -3,12 +3,12 @@ import CloseCircleFilled from '@ant-design/icons-vue/CloseCircleFilled';
import { getInputClassName } from './Input';
import PropTypes from '../_util/vue-types';
import { cloneElement } from '../_util/vnode';
import { getComponentFromProp } from '../_util/props-util';
import { getComponent } from '../_util/props-util';
export function hasPrefixSuffix(instance) {
return !!(
getComponentFromProp(instance, 'prefix') ||
getComponentFromProp(instance, 'suffix') ||
getComponent(instance, 'prefix') ||
getComponent(instance, 'suffix') ||
instance.$props.allowClear
);
}
@ -16,6 +16,8 @@ export function hasPrefixSuffix(instance) {
const ClearableInputType = ['text', 'input'];
const ClearableLabeledInput = {
name: 'ClearableLabeledInput',
inheritAttrs: false,
props: {
prefixCls: PropTypes.string,
inputType: PropTypes.oneOf(ClearableInputType),
@ -30,7 +32,6 @@ const ClearableLabeledInput = {
prefix: PropTypes.any,
addonBefore: PropTypes.any,
addonAfter: PropTypes.any,
className: PropTypes.string,
readOnly: PropTypes.bool,
},
methods: {
@ -71,7 +72,7 @@ const ClearableLabeledInput = {
const suffix = this.renderSuffix(prefixCls);
if (!hasPrefixSuffix(this)) {
return cloneElement(element, {
props: { value: props.value },
value: props.value,
});
}
@ -91,7 +92,7 @@ const ClearableLabeledInput = {
{prefix}
{cloneElement(element, {
style: null,
props: { value: props.value },
value: props.value,
class: getInputClassName(prefixCls, props.size, props.disabled),
})}
{suffix}
@ -100,7 +101,8 @@ const ClearableLabeledInput = {
},
renderInputWithLabel(prefixCls, labeledElement) {
const { addonBefore, addonAfter, style, size, className } = this.$props;
const { addonBefore, addonAfter, size } = this.$props;
const { style, class: className } = this.$attrs;
// Not wrap when there is not addons
if (!addonBefore && !addonAfter) {
return labeledElement;
@ -136,11 +138,10 @@ const ClearableLabeledInput = {
},
renderTextAreaWithClearIcon(prefixCls, element) {
const { value, allowClear, className, style } = this.$props;
const { value, allowClear } = this.$props;
const { style, class: className } = this.$attrs;
if (!allowClear) {
return cloneElement(element, {
props: { value },
});
return cloneElement(element, { value });
}
const affixWrapperCls = classNames(
className,
@ -151,7 +152,7 @@ const ClearableLabeledInput = {
<span class={affixWrapperCls} style={style}>
{cloneElement(element, {
style: null,
props: { value },
value,
})}
{this.renderClearIcon(prefixCls)}
</span>

View File

@ -1,5 +1,6 @@
import { inject } from 'vue';
import PropTypes from '../_util/vue-types';
import { filterEmpty, getListeners } from '../_util/props-util';
import { filterEmpty, getSlot } from '../_util/props-util';
import { ConfigConsumerProps } from '../config-provider';
export default {
@ -13,8 +14,10 @@ export default {
},
compact: Boolean,
},
inject: {
configProvider: { default: () => ConfigConsumerProps },
setup() {
return {
configProvider: inject('configProvider', ConfigConsumerProps),
};
},
computed: {
classes() {
@ -30,12 +33,7 @@ export default {
};
},
},
methods: {},
render() {
return (
<span class={this.classes} {...{ on: getListeners(this) }}>
{filterEmpty(this.$slots.default)}
</span>
);
return <span class={this.classes}>{filterEmpty(getSlot(this))}</span>;
},
};

View File

@ -1,8 +1,8 @@
import { inject } from 'vue';
import classNames from 'classnames';
import TextArea from './TextArea';
import omit from 'omit.js';
import inputProps from './inputProps';
import { hasProp, getComponentFromProp, getListeners, getOptionProps } from '../_util/props-util';
import { hasProp, getComponent, getOptionProps } from '../_util/props-util';
import { ConfigConsumerProps } from '../config-provider';
import ClearableLabeledInput from './ClearableLabeledInput';
@ -52,15 +52,13 @@ export function getInputClassName(prefixCls, size, disabled) {
export default {
name: 'AInput',
inheritAttrs: false,
model: {
prop: 'value',
event: 'change.value',
},
props: {
...inputProps,
},
inject: {
configProvider: { default: () => ConfigConsumerProps },
setup() {
return {
configProvider: inject('configProvider', ConfigConsumerProps),
};
},
data() {
const props = this.$props;
@ -89,14 +87,22 @@ export default {
},
methods: {
focus() {
this.$refs.input.focus();
this.input.focus();
},
blur() {
this.$refs.input.blur();
this.input.blur();
},
select() {
this.$refs.input.select();
this.input.select();
},
saveClearableInput(input) {
this.clearableInput = input;
},
saveInput(input) {
this.input = input;
},
setValue(value, callback) {
@ -109,13 +115,11 @@ export default {
callback && callback();
});
} else {
//
// https://github.com/vueComponent/ant-design-vue/issues/2207modal new
// this.$forceUpdate();
this.$forceUpdate();
}
},
onChange(e) {
this.$emit('change.value', e.target.value);
this.$emit('update:value', e.target.value);
this.$emit('change', e);
this.$emit('input', e);
},
@ -123,9 +127,9 @@ export default {
this.setValue('', () => {
this.focus();
});
resolveOnChange(this.$refs.input, e, this.onChange);
resolveOnChange(this.input, e, this.onChange);
},
renderInput(prefixCls) {
renderInput(prefixCls, { addonBefore, addonAfter }) {
const otherProps = omit(this.$props, [
'prefixCls',
'addonBefore',
@ -133,42 +137,43 @@ export default {
'prefix',
'suffix',
'allowClear',
'value',
'defaultValue',
'lazy',
'size',
'inputType',
'className',
'autoFocus',
'inputPrefixCls',
'loading',
]);
const { stateValue, handleKeyDown, handleChange, size, disabled } = this;
const { handleKeyDown, handleChange, size, disabled, $attrs } = this;
const inputProps = {
directives: [{ name: 'ant-input' }],
domProps: {
value: fixControlledValue(stateValue),
},
attrs: { ...otherProps, ...this.$attrs },
on: {
...getListeners(this),
keydown: handleKeyDown,
input: handleChange,
change: noop,
},
class: getInputClassName(prefixCls, size, disabled),
ref: 'input',
...otherProps,
...$attrs,
onKeydown: handleKeyDown,
class: classNames(getInputClassName(prefixCls, size, disabled), {
[$attrs.class]: $attrs.class && !addonBefore && !addonAfter,
}),
ref: this.saveInput,
key: 'ant-input',
};
return <input {...inputProps} />;
// vue bug
if (inputProps.maxLength === undefined) {
delete inputProps.maxLength;
}
return <input {...inputProps} onInput={handleChange} onChange={noop} />;
},
clearPasswordValueAttribute() {
// https://github.com/ant-design/ant-design/issues/20541
this.removePasswordTimeout = setTimeout(() => {
if (
this.$refs.input &&
this.$refs.input.getAttribute &&
this.$refs.input.getAttribute('type') === 'password' &&
this.$refs.input.hasAttribute('value')
this.input &&
this.input.getAttribute &&
this.input.getAttribute('type') === 'password' &&
this.input.hasAttribute('value')
) {
this.$refs.input.removeAttribute('value');
this.input.removeAttribute('value');
}
});
},
@ -177,7 +182,7 @@ export default {
// https://github.com/vueComponent/ant-design-vue/issues/2203
if (((e.isComposing || composing) && this.lazy) || this.stateValue === value) return;
this.setValue(value, this.clearPasswordValueAttribute);
resolveOnChange(this.$refs.input, e, this.onChange);
resolveOnChange(this.input, e, this.onChange);
},
handleKeyDown(e) {
if (e.keyCode === 13) {
@ -187,42 +192,37 @@ export default {
},
},
render() {
if (this.$props.type === 'textarea') {
const textareaProps = {
props: this.$props,
attrs: this.$attrs,
on: {
...getListeners(this),
input: this.handleChange,
keydown: this.handleKeyDown,
change: noop,
},
};
return <TextArea {...textareaProps} ref="input" />;
}
// if (this.$props.type === 'textarea') {
// const textareaProps = {
// ...this.$props,
// ...this.$attrs,
// onInput: this.handleChange,
// onKeydown: this.handleKeyDown,
// onChange: noop,
// };
// return <TextArea {...textareaProps} ref="input" />;
// }
const { prefixCls: customizePrefixCls } = this.$props;
const { stateValue } = this.$data;
const getPrefixCls = this.configProvider.getPrefixCls;
const prefixCls = getPrefixCls('input', customizePrefixCls);
const addonAfter = getComponentFromProp(this, 'addonAfter');
const addonBefore = getComponentFromProp(this, 'addonBefore');
const suffix = getComponentFromProp(this, 'suffix');
const prefix = getComponentFromProp(this, 'prefix');
const addonAfter = getComponent(this, 'addonAfter');
const addonBefore = getComponent(this, 'addonBefore');
const suffix = getComponent(this, 'suffix');
const prefix = getComponent(this, 'prefix');
const props = {
props: {
...getOptionProps(this),
prefixCls,
inputType: 'input',
value: fixControlledValue(stateValue),
element: this.renderInput(prefixCls),
handleReset: this.handleReset,
addonAfter,
addonBefore,
suffix,
prefix,
},
on: getListeners(this),
...this.$attrs,
...getOptionProps(this),
prefixCls,
inputType: 'input',
value: fixControlledValue(stateValue),
element: this.renderInput(prefixCls, { addonAfter, addonBefore }),
handleReset: this.handleReset,
addonAfter,
addonBefore,
suffix,
prefix,
};
return <ClearableLabeledInput {...props} />;
return <ClearableLabeledInput {...props} ref={this.saveClearableInput} />;
},
};

View File

@ -1,5 +1,5 @@
import classNames from 'classnames';
import { getComponentFromProp, getOptionProps, getListeners } from '../_util/props-util';
import { getComponent, getOptionProps } from '../_util/props-util';
import Input from './Input';
import EyeOutlined from '@ant-design/icons-vue/EyeOutlined';
import EyeInvisibleOutlined from '@ant-design/icons-vue/EyeInvisibleOutlined';
@ -8,18 +8,14 @@ import PropTypes from '../_util/vue-types';
import BaseMixin from '../_util/BaseMixin';
const ActionMap = {
click: 'click',
hover: 'mouseover',
click: 'onClick',
hover: 'onMouseover',
};
export default {
name: 'AInputPassword',
mixins: [BaseMixin],
inheritAttrs: false,
model: {
prop: 'value',
event: 'change.value',
},
props: {
...inputProps,
prefixCls: PropTypes.string.def('ant-input-password'),
@ -33,11 +29,14 @@ export default {
};
},
methods: {
saveInput(node) {
this.input = node;
},
focus() {
this.$refs.input.focus();
this.input.focus();
},
blur() {
this.$refs.input.blur();
this.input.blur();
},
onVisibleChange() {
if (this.disabled) {
@ -51,18 +50,16 @@ export default {
const { prefixCls, action } = this.$props;
const iconTrigger = ActionMap[action] || '';
const iconProps = {
on: {
[iconTrigger]: this.onVisibleChange,
mousedown: e => {
// Prevent focused state lost
// https://github.com/ant-design/ant-design/issues/15173
e.preventDefault();
},
mouseup: e => {
// Prevent focused state lost
// https://github.com/ant-design/ant-design/pull/23633/files
e.preventDefault();
},
[iconTrigger]: this.onVisibleChange,
onMousedown: e => {
// Prevent focused state lost
// https://github.com/ant-design/ant-design/issues/15173
e.preventDefault();
},
onMouseup: e => {
// Prevent focused state lost
// https://github.com/ant-design/ant-design/pull/23633/files
e.preventDefault();
},
class: `${prefixCls}-icon`,
key: 'passwordIcon',
@ -83,28 +80,24 @@ export default {
visibilityToggle,
...restProps
} = getOptionProps(this);
const { class: className } = this.$attrs;
const suffixIcon = visibilityToggle && this.getIcon();
const inputClassName = classNames(prefixCls, {
const inputClassName = classNames(prefixCls, className, {
[`${prefixCls}-${size}`]: !!size,
});
const inputProps = {
props: {
...restProps,
prefixCls: inputPrefixCls,
size,
suffix: suffixIcon,
prefix: getComponentFromProp(this, 'prefix'),
addonAfter: getComponentFromProp(this, 'addonAfter'),
addonBefore: getComponentFromProp(this, 'addonBefore'),
},
attrs: {
...this.$attrs,
type: this.visible ? 'text' : 'password',
},
...restProps,
prefixCls: inputPrefixCls,
size,
suffix: suffixIcon,
prefix: getComponent(this, 'prefix'),
addonAfter: getComponent(this, 'addonAfter'),
addonBefore: getComponent(this, 'addonBefore'),
...this.$attrs,
type: this.visible ? 'text' : 'password',
class: inputClassName,
ref: 'input',
on: getListeners(this),
};
return <Input {...inputProps} />;
return <Input {...inputProps} ref={this.saveInput} />;
},
};

View File

@ -7,7 +7,7 @@ import warning from '../_util/warning';
import BaseMixin from '../_util/BaseMixin';
import inputProps from './inputProps';
import PropTypes from '../_util/vue-types';
import { getOptionProps, getListeners } from '../_util/props-util';
import { getOptionProps } from '../_util/props-util';
const RESIZE_STATUS_NONE = 0;
const RESIZE_STATUS_RESIZING = 1;
@ -20,6 +20,7 @@ const TextAreaProps = {
};
const ResizableTextArea = {
name: 'ResizableTextArea',
inheritAttrs: false,
props: TextAreaProps,
data() {
return {
@ -43,6 +44,9 @@ const ResizableTextArea = {
},
},
methods: {
saveTextArea(textArea) {
this.textArea = textArea;
},
handleResize(size) {
const { resizeStatus } = this.$data;
const { autoSize } = this.$props;
@ -62,11 +66,11 @@ const ResizableTextArea = {
resizeTextarea() {
const autoSize = this.$props.autoSize || this.$props.autosize;
if (!autoSize || !this.$refs.textArea) {
if (!autoSize || !this.textArea) {
return;
}
const { minRows, maxRows } = autoSize;
const textareaStyles = calculateNodeHeight(this.$refs.textArea, false, minRows, maxRows);
const textareaStyles = calculateNodeHeight(this.textArea, false, minRows, maxRows);
this.setState({ textareaStyles, resizeStatus: RESIZE_STATUS_RESIZING }, () => {
raf.cancel(this.resizeFrameId);
this.resizeFrameId = raf(() => {
@ -82,10 +86,10 @@ const ResizableTextArea = {
// https://github.com/ant-design/ant-design/issues/21870
fixFirefoxAutoScroll() {
try {
if (document.activeElement === this.$refs.textArea) {
const currentStart = this.$refs.textArea.selectionStart;
const currentEnd = this.$refs.textArea.selectionEnd;
this.$refs.textArea.setSelectionRange(currentStart, currentEnd);
if (document.activeElement === this.textArea) {
const currentStart = this.textArea.selectionStart;
const currentEnd = this.textArea.selectionEnd;
this.textArea.setSelectionRange(currentStart, currentEnd);
}
} catch (e) {
// Fix error in Chrome:
@ -95,8 +99,8 @@ const ResizableTextArea = {
},
renderTextArea() {
const props = getOptionProps(this);
const { prefixCls, autoSize, autosize, disabled } = props;
const props = { ...getOptionProps(this), ...this.$attrs };
const { prefixCls, autoSize, autosize, disabled, class: className } = props;
const { textareaStyles, resizeStatus } = this.$data;
warning(
autosize === undefined,
@ -105,35 +109,33 @@ const ResizableTextArea = {
);
const otherProps = omit(props, [
'prefixCls',
'onPressEnter',
'autoSize',
'autosize',
'defaultValue',
'allowClear',
'type',
'lazy',
'value',
]);
const cls = classNames(prefixCls, {
const cls = classNames(prefixCls, className, {
[`${prefixCls}-disabled`]: disabled,
});
const domProps = {};
// Fix https://github.com/ant-design/ant-design/issues/6776
// Make sure it could be reset when using form.getFieldDecorator
if ('value' in props) {
domProps.value = props.value || '';
if ('value' in otherProps) {
otherProps.value = otherProps.value || '';
}
const style = {
...props.style,
...textareaStyles,
...(resizeStatus === RESIZE_STATUS_RESIZING
? { overflowX: 'hidden', overflowY: 'hidden' }
: null),
};
const textareaProps = {
attrs: otherProps,
domProps,
...otherProps,
style,
class: cls,
on: omit(getListeners(this), 'pressEnter'),
directives: [
{
name: 'ant-input',
@ -142,7 +144,7 @@ const ResizableTextArea = {
};
return (
<ResizeObserver onResize={this.handleResize} disabled={!(autoSize || autosize)}>
<textarea {...textareaProps} ref="textArea" />
<textarea {...textareaProps} ref={this.saveTextArea} />
</ResizeObserver>
);
},

View File

@ -1,3 +1,4 @@
import { inject } from 'vue';
import classNames from 'classnames';
import { isMobile } from 'is-mobile';
import Input from './Input';
@ -7,25 +8,27 @@ import inputProps from './inputProps';
import Button from '../button';
import { cloneElement } from '../_util/vnode';
import PropTypes from '../_util/vue-types';
import { getOptionProps, getComponentFromProp, getListeners } from '../_util/props-util';
import { getOptionProps, getComponent } from '../_util/props-util';
import { ConfigConsumerProps } from '../config-provider';
import isPlainObject from 'lodash/isPlainObject';
export default {
name: 'AInputSearch',
inheritAttrs: false,
model: {
prop: 'value',
event: 'change.value',
},
props: {
...inputProps,
// https://github.com/vueComponent/ant-design-vue/issues/1916
enterButton: PropTypes.any,
},
inject: {
configProvider: { default: () => ConfigConsumerProps },
setup() {
return {
configProvider: inject('configProvider', ConfigConsumerProps),
};
},
methods: {
saveInput(node) {
this.input = node;
},
onChange(e) {
if (e && e.target && e.type === 'click') {
this.$emit('search', e.target.value, e);
@ -36,21 +39,21 @@ export default {
if (this.loading || this.disabled) {
return;
}
this.$emit('search', this.$refs.input.stateValue, e);
this.$emit('search', this.input.stateValue, e);
if (!isMobile({ tablet: true })) {
this.$refs.input.focus();
this.input.focus();
}
},
focus() {
this.$refs.input.focus();
this.input.focus();
},
blur() {
this.$refs.input.blur();
this.input.blur();
},
renderLoading(prefixCls) {
const { size } = this.$props;
let enterButton = getComponentFromProp(this, 'enterButton');
let enterButton = getComponent(this, 'enterButton');
// <a-input-search enterButton /> enterButton any enterButton
enterButton = enterButton || enterButton === '';
if (enterButton) {
@ -64,8 +67,8 @@ export default {
},
renderSuffix(prefixCls) {
const { loading } = this;
const suffix = getComponentFromProp(this, 'suffix');
let enterButton = getComponentFromProp(this, 'enterButton');
const suffix = getComponent(this, 'suffix');
let enterButton = getComponent(this, 'enterButton');
// <a-input-search enterButton /> enterButton any enterButton
enterButton = enterButton || enterButton === '';
if (loading && !enterButton) {
@ -93,9 +96,9 @@ export default {
renderAddonAfter(prefixCls) {
const { size, disabled, loading } = this;
const btnClassName = `${prefixCls}-button`;
let enterButton = getComponentFromProp(this, 'enterButton');
let enterButton = getComponent(this, 'enterButton');
enterButton = enterButton || enterButton === '';
const addonAfter = getComponentFromProp(this, 'addonAfter');
const addonAfter = getComponent(this, 'addonAfter');
if (loading && enterButton) {
return [this.renderLoading(prefixCls), addonAfter];
}
@ -103,16 +106,15 @@ export default {
const enterButtonAsElement = Array.isArray(enterButton) ? enterButton[0] : enterButton;
let button;
const isAntdButton =
enterButtonAsElement.componentOptions &&
enterButtonAsElement.componentOptions.Ctor.extendOptions.__ANT_BUTTON;
if (enterButtonAsElement.tag === 'button' || isAntdButton) {
enterButtonAsElement.type &&
isPlainObject(enterButtonAsElement.type) &&
enterButtonAsElement.type.__ANT_BUTTON;
if (enterButtonAsElement.tagName === 'button' || isAntdButton) {
button = cloneElement(enterButtonAsElement, {
key: 'enterButton',
class: isAntdButton ? btnClassName : '',
props: isAntdButton ? { size } : {},
on: {
click: this.onSearch,
},
...(isAntdButton ? { size } : {}),
onClick: this.onSearch,
});
} else {
button = (
@ -140,19 +142,23 @@ export default {
prefixCls: customizePrefixCls,
inputPrefixCls: customizeInputPrefixCls,
size,
loading,
...others
} = getOptionProps(this);
class: className,
...restProps
} = { ...getOptionProps(this), ...this.$attrs };
delete restProps.onSearch;
delete restProps.loading;
delete restProps.enterButton;
delete restProps.addonBefore;
const getPrefixCls = this.configProvider.getPrefixCls;
const prefixCls = getPrefixCls('input-search', customizePrefixCls);
const inputPrefixCls = getPrefixCls('input', customizeInputPrefixCls);
let enterButton = getComponentFromProp(this, 'enterButton');
const addonBefore = getComponentFromProp(this, 'addonBefore');
let enterButton = getComponent(this, 'enterButton');
const addonBefore = getComponent(this, 'addonBefore');
enterButton = enterButton || enterButton === '';
let inputClassName;
if (enterButton) {
inputClassName = classNames(prefixCls, {
inputClassName = classNames(prefixCls, className, {
[`${prefixCls}-enter-button`]: !!enterButton,
[`${prefixCls}-${size}`]: !!size,
});
@ -160,27 +166,18 @@ export default {
inputClassName = prefixCls;
}
const on = { ...getListeners(this) };
delete on.search;
const inputProps = {
props: {
...others,
prefixCls: inputPrefixCls,
size,
suffix: this.renderSuffix(prefixCls),
prefix: getComponentFromProp(this, 'prefix'),
addonAfter: this.renderAddonAfter(prefixCls),
addonBefore,
className: inputClassName,
},
attrs: this.$attrs,
ref: 'input',
on: {
pressEnter: this.onSearch,
...on,
change: this.onChange,
},
...restProps,
prefixCls: inputPrefixCls,
size,
suffix: this.renderSuffix(prefixCls),
prefix: getComponent(this, 'prefix'),
addonAfter: this.renderAddonAfter(prefixCls),
addonBefore,
class: inputClassName,
onPressEnter: this.onSearch,
onChange: this.onChange,
};
return <Input {...inputProps} />;
return <Input {...inputProps} ref={this.saveInput} />;
},
};

View File

@ -1,7 +1,8 @@
import { inject } from 'vue';
import ClearableLabeledInput from './ClearableLabeledInput';
import ResizableTextArea from './ResizableTextArea';
import inputProps from './inputProps';
import hasProp, { getListeners, getOptionProps } from '../_util/props-util';
import { hasProp, getOptionProps } from '../_util/props-util';
import { ConfigConsumerProps } from '../config-provider';
import { fixControlledValue, resolveOnChange } from './Input';
import PropTypes from '../_util/vue-types';
@ -15,15 +16,13 @@ const TextAreaProps = {
export default {
name: 'ATextarea',
inheritAttrs: false,
model: {
prop: 'value',
event: 'change.value',
},
props: {
...TextAreaProps,
},
inject: {
configProvider: { default: () => ConfigConsumerProps },
setup() {
return {
configProvider: inject('configProvider', ConfigConsumerProps),
};
},
data() {
const value = typeof this.value === 'undefined' ? this.defaultValue : this.value;
@ -52,9 +51,7 @@ export default {
callback && callback();
});
} else {
//
// https://github.com/vueComponent/ant-design-vue/issues/2207modal new
// this.$forceUpdate();
this.$forceUpdate();
}
},
handleKeyDown(e) {
@ -64,7 +61,7 @@ export default {
this.$emit('keydown', e);
},
onChange(e) {
this.$emit('change.value', e.target.value);
this.$emit('update:value', e.target.value);
this.$emit('change', e);
this.$emit('input', e);
},
@ -73,41 +70,43 @@ export default {
if (((e.isComposing || composing) && this.lazy) || this.stateValue === value) return;
this.setValue(e.target.value, () => {
this.$refs.resizableTextArea.resizeTextarea();
this.resizableTextArea.resizeTextarea();
});
resolveOnChange(this.$refs.resizableTextArea.$refs.textArea, e, this.onChange);
resolveOnChange(this.resizableTextArea.textArea, e, this.onChange);
},
focus() {
this.$refs.resizableTextArea.$refs.textArea.focus();
this.resizableTextArea.textArea.focus();
},
blur() {
this.$refs.resizableTextArea.$refs.textArea.blur();
this.resizableTextArea.textArea.blur();
},
saveTextArea(resizableTextArea) {
this.resizableTextArea = resizableTextArea;
},
saveClearableInput(clearableInput) {
this.clearableInput = clearableInput;
},
handleReset(e) {
this.setValue('', () => {
this.$refs.resizableTextArea.renderTextArea();
this.resizableTextArea.renderTextArea();
this.focus();
});
resolveOnChange(this.$refs.resizableTextArea.$refs.textArea, e, this.onChange);
resolveOnChange(this.resizableTextArea.textArea, e, this.onChange);
},
renderTextArea(prefixCls) {
const props = getOptionProps(this);
const resizeProps = {
props: {
...props,
prefixCls,
},
on: {
...getListeners(this),
input: this.handleChange,
keydown: this.handleKeyDown,
},
attrs: this.$attrs,
...props,
...this.$attrs,
prefixCls,
onInput: this.handleChange,
onKeydown: this.handleKeyDown,
};
return <ResizableTextArea {...resizeProps} ref="resizableTextArea" />;
return <ResizableTextArea {...resizeProps} ref={this.saveTextArea} />;
},
},
render() {
@ -116,16 +115,14 @@ export default {
const prefixCls = getPrefixCls('input', customizePrefixCls);
const props = {
props: {
...getOptionProps(this),
prefixCls,
inputType: 'text',
value: fixControlledValue(stateValue),
element: this.renderTextArea(prefixCls),
handleReset: this.handleReset,
},
on: getListeners(this),
...getOptionProps(this),
...this.$attrs,
prefixCls,
inputType: 'text',
value: fixControlledValue(stateValue),
element: this.renderTextArea(prefixCls),
handleReset: this.handleReset,
};
return <ClearableLabeledInput {...props} />;
return <ClearableLabeledInput {...props} ref={this.saveClearableInput} />;
},
};

View File

@ -40,7 +40,7 @@ describe('TextArea', () => {
sync: false,
});
const mockFunc = jest.spyOn(wrapper.vm.$refs.resizableTextArea, 'resizeTextarea');
const mockFunc = jest.spyOn(wrapper.vm.resizableTextArea, 'resizeTextarea');
await asyncExpect(() => {
wrapper.setProps({ value: '1111\n2222\n3333' });
});

View File

@ -1,13 +1,8 @@
import Vue from 'vue';
import Input from './Input';
import Group from './Group';
import Search from './Search';
import TextArea from './TextArea';
import Password from './Password';
import antInputDirective from '../_util/antInputDirective';
import Base from '../base';
Vue.use(antInputDirective);
Input.Group = Group;
Input.Search = Search;
@ -15,13 +10,12 @@ Input.TextArea = TextArea;
Input.Password = Password;
/* istanbul ignore next */
Input.install = function(Vue) {
Vue.use(Base);
Vue.component(Input.name, Input);
Vue.component(Input.Group.name, Input.Group);
Vue.component(Input.Search.name, Input.Search);
Vue.component(Input.TextArea.name, Input.TextArea);
Vue.component(Input.Password.name, Input.Password);
Input.install = function(app) {
app.component(Input.name, Input);
app.component(Input.Group.name, Input.Group);
app.component(Input.Search.name, Input.Search);
app.component(Input.TextArea.name, Input.TextArea);
app.component(Input.Password.name, Input.Password);
};
export default Input;

View File

@ -32,5 +32,4 @@ export default {
},
maxLength: PropTypes.number,
loading: PropTypes.bool,
className: PropTypes.string,
};

View File

@ -4,7 +4,7 @@
</div>
</template>
<script>
import demo from '../antdv-demo/docs/rate/demo/index';
import demo from '../antdv-demo/docs/input/demo/tooltip';
export default {
components: {

View File

@ -1,7 +1,20 @@
import '@babel/polyfill';
import { createApp } from 'vue';
import App from './App.vue';
import { Rate, Button, Upload, Icon, Modal, Progress, notification, message } from 'ant-design-vue';
import {
Input,
Rate,
Button,
Upload,
Icon,
Modal,
Progress,
Tooltip,
Col,
Row,
notification,
message,
} from 'ant-design-vue';
import 'ant-design-vue/style.js';
const basic = {
@ -24,4 +37,8 @@ app
.use(Modal)
.use(Progress)
.use(Rate)
.use(Input)
.use(Tooltip)
.use(Col)
.use(Row)
.mount('#app');