diff --git a/src/input/_example/align.tsx b/src/input/_example/align.tsx
index 7938608..d0071a4 100644
--- a/src/input/_example/align.tsx
+++ b/src/input/_example/align.tsx
@@ -4,8 +4,6 @@ import 'tdesign-web-components/space';
import { Component } from 'omi';
export default class InputAlign extends Component {
- inputValue = '';
-
render() {
return (
diff --git a/src/input/_example/auto-width.tsx b/src/input/_example/auto-width.tsx
index 1e48bfe..9f253d6 100644
--- a/src/input/_example/auto-width.tsx
+++ b/src/input/_example/auto-width.tsx
@@ -13,6 +13,7 @@ export default class InputAutowidth extends Component {
defaultValue="宽度自适应"
onChange={(value) => {
this.inputValue = value;
+ this.update();
}}
/>
diff --git a/src/input/_example/base.tsx b/src/input/_example/base.tsx
index 594d69b..e538ac3 100644
--- a/src/input/_example/base.tsx
+++ b/src/input/_example/base.tsx
@@ -16,6 +16,7 @@ export default class InputBase extends Component {
placeholder="请输入内容(无默认值)"
onChange={(value) => {
this.value1 = value;
+ this.update();
console.log('change', value);
}}
onFocus={() => {
@@ -31,6 +32,7 @@ export default class InputBase extends Component {
onChange={(value) => {
console.log(value);
this.value2 = value;
+ this.update();
}}
onEnter={(value) => {
console.log(value);
diff --git a/src/input/_example/borderless.tsx b/src/input/_example/borderless.tsx
index 12239a0..3c9ebc7 100644
--- a/src/input/_example/borderless.tsx
+++ b/src/input/_example/borderless.tsx
@@ -15,6 +15,7 @@ export default class InputBase extends Component {
placeholder="请输入内容(无默认值)"
onChange={(value) => {
this.value1 = value;
+ this.update();
console.log(value);
}}
/>
@@ -24,6 +25,7 @@ export default class InputBase extends Component {
onChange={(value) => {
console.log(value);
this.value2 = value;
+ this.update();
}}
onEnter={(value) => {
console.log(value);
diff --git a/src/input/_example/clearable.tsx b/src/input/_example/clearable.tsx
index 5f00f25..da6ccbc 100644
--- a/src/input/_example/clearable.tsx
+++ b/src/input/_example/clearable.tsx
@@ -1,6 +1,6 @@
+import 'tdesign-icons-web-components/esm/components/lock-on';
import 'tdesign-web-components/input';
import 'tdesign-web-components/space';
-import 'tdesign-icons-web-components/esm/components/lock-on';
import { Component } from 'omi';
@@ -10,7 +10,15 @@ export default class InputBase extends Component {
render() {
return (
-
+ {
+ this.value1 = value;
+ this.update();
+ }}
+ clearable
+ />
);
}
diff --git a/src/input/_example/format.tsx b/src/input/_example/format.tsx
index 72788b2..620ffbb 100644
--- a/src/input/_example/format.tsx
+++ b/src/input/_example/format.tsx
@@ -21,6 +21,7 @@ export default class InputForMat extends Component {
value={this.inputValue}
onChange={(value) => {
this.inputValue = value;
+ this.update();
}}
status={inputStatus}
format={format}
diff --git a/src/input/_example/password.tsx b/src/input/_example/password.tsx
index 50b2d14..4fa7285 100644
--- a/src/input/_example/password.tsx
+++ b/src/input/_example/password.tsx
@@ -1,6 +1,6 @@
+import 'tdesign-icons-web-components/esm/components/lock-on';
import 'tdesign-web-components/input';
import 'tdesign-web-components/space';
-import 'tdesign-icons-web-components/esm/components/lock-on';
import { Component } from 'omi';
@@ -12,8 +12,26 @@ export default class InputBase extends Component {
render() {
return (
- } />
- } />
+ }
+ onChange={(value) => {
+ this.value1 = value;
+ this.update();
+ }}
+ />
+ }
+ onChange={(value) => {
+ this.value2 = value;
+ this.update();
+ }}
+ />
);
}
diff --git a/src/input/_example/status.tsx b/src/input/_example/status.tsx
index c662cff..af5ea7b 100644
--- a/src/input/_example/status.tsx
+++ b/src/input/_example/status.tsx
@@ -18,6 +18,7 @@ export default class InputStatus extends Component {
value={this.inputValue}
onChange={(value) => {
this.inputValue = value;
+ this.update();
}}
/>
{
this.inputValue = value;
+ this.update();
}}
/>
@@ -35,6 +37,7 @@ export default class InputStatus extends Component {
value={this.inputValue}
onChange={(value) => {
this.inputValue = value;
+ this.update();
}}
status="success"
/>
@@ -43,6 +46,7 @@ export default class InputStatus extends Component {
value={this.inputValue}
onChange={(value) => {
this.inputValue = value;
+ this.update();
}}
status="warning"
/>
@@ -51,6 +55,7 @@ export default class InputStatus extends Component {
value={this.inputValue}
onChange={(value) => {
this.inputValue = value;
+ this.update();
}}
status="error"
/>
@@ -62,6 +67,7 @@ export default class InputStatus extends Component {
value={this.inputValue}
onChange={(value) => {
this.inputValue = value;
+ this.update();
}}
/>
{
this.inputValue = value;
+ this.update();
}}
status="success"
/>
@@ -79,6 +86,7 @@ export default class InputStatus extends Component {
value={this.inputValue}
onChange={(value) => {
this.inputValue = value;
+ this.update();
}}
status="warning"
/>
@@ -88,6 +96,7 @@ export default class InputStatus extends Component {
value={this.inputValue}
onChange={(value) => {
this.inputValue = value;
+ this.update();
}}
status="error"
/>
diff --git a/src/input/input.tsx b/src/input/input.tsx
index 4eabe0e..334f27e 100644
--- a/src/input/input.tsx
+++ b/src/input/input.tsx
@@ -94,7 +94,7 @@ export default class Input extends Component {
composingRef = createRef();
- value;
+ innerValue;
composingValue = '';
@@ -110,6 +110,10 @@ export default class Input extends Component {
eventProps;
+ private get isControlled() {
+ return Reflect.has(this.props, 'value');
+ }
+
private handlePasswordVisible = (e: MouseEvent) => {
e.stopImmediatePropagation();
if (this.props.disabled) return;
@@ -123,7 +127,7 @@ export default class Input extends Component {
const { maxlength, maxcharacter, allowInputOverMax, status, onValidate, onChange } = this.props;
const { getValueByLimitNumber } = useLengthLimit({
- value: this.value === undefined ? undefined : String(this.value),
+ value: this.innerValue === undefined ? undefined : String(this.innerValue),
status,
maxlength,
maxcharacter,
@@ -140,7 +144,9 @@ export default class Input extends Component {
// 完成中文输入时同步一次 composingValue
this.composingValue = newStr;
// 防止输入中文后移开光标触发mouseleave时value没更新
- this.value = newStr;
+ if (!this.isControlled) {
+ this.innerValue = newStr;
+ }
const { onValidateChange } = useLengthLimit({
value: newStr === undefined ? undefined : String(newStr),
status: this.status,
@@ -195,7 +201,6 @@ export default class Input extends Component {
private handleClear = (e: MouseEvent) => {
const { onChange, onClear } = this.props;
this.composingValue = '';
- this.value = '';
this.update();
onChange?.('', { e });
onClear?.({ e });
@@ -204,20 +209,27 @@ export default class Input extends Component {
private handleKeyDown = (e: KeyboardEvent) => {
const { onEnter } = this.props;
const { key, currentTarget }: { key: string; currentTarget: any } = e;
- this.value = '';
key === 'Enter' && onEnter?.(currentTarget.value, { e });
this.props.onMyKeydown?.(currentTarget.value, { e });
+ this.props.onKeydown?.(currentTarget.value, { e });
+ // 防止 最外层 onKeydown
+ e.stopPropagation();
};
private handleKeyUp = (e: KeyboardEvent) => {
const { currentTarget }: { currentTarget: any } = e;
this.props.onMyKeyup?.(currentTarget.value, { e });
+ this.props.onKeyup?.(currentTarget.value, { e });
+ // 防止 最外层 onKeyup
+ e.stopPropagation();
};
private handleKeyPress = (e: KeyboardEvent) => {
const { onKeypress } = this.props;
const { currentTarget }: { currentTarget: any } = e;
onKeypress?.(currentTarget.value, { e });
+ // 防止 最外层 onKeypress
+ e.stopPropagation();
};
private handleCompositionStart = (e: CompositionEvent) => {
@@ -251,7 +263,7 @@ export default class Input extends Component {
private resizeObserver: ResizeObserver | null = null;
install() {
- this.value = this.props.defaultValue || this.props.value;
+ this.innerValue = this.props.value || this.props.defaultValue;
this.status = this.props.status;
}
@@ -278,9 +290,12 @@ export default class Input extends Component {
return;
}
const target = e.currentTarget as any;
- this.value = target.value;
+ if (!this.isControlled) {
+ this.innerValue = target.value;
+ }
+
const { getValueByLimitNumber, onValidateChange } = useLengthLimit({
- value: this.value === undefined ? undefined : String(this.value),
+ value: this.innerValue === undefined ? undefined : String(this.innerValue),
status: this.status,
maxlength: this.props.maxlength,
maxcharacter: this.props.maxcharacter,
@@ -288,7 +303,9 @@ export default class Input extends Component {
onValidate: this.props.onValidate,
});
const limitedValue = getValueByLimitNumber(target.value);
- this.value = limitedValue;
+ if (!this.isControlled) {
+ this.innerValue = limitedValue;
+ }
this.composingValue = limitedValue;
this.props.onChange?.(limitedValue);
if (!this.props.allowInputOverMax) {
@@ -298,6 +315,15 @@ export default class Input extends Component {
});
}
+ receiveProps(props: InputProps | OmiProps, oldProps: InputProps | OmiProps) {
+ if (
+ (this.isControlled && props.value !== oldProps.value) ||
+ (Reflect.has(oldProps, 'value') && !this.isControlled)
+ ) {
+ this.innerValue = props.value;
+ }
+ }
+
render(props: OmiProps) {
const {
innerClass,
@@ -335,7 +361,7 @@ export default class Input extends Component {
delete restProps.style;
const { limitNumber, tStatus } = useLengthLimit({
- value: this.value === undefined ? undefined : String(this.value),
+ value: this.innerValue === undefined ? undefined : String(this.innerValue),
status,
maxlength,
maxcharacter,
@@ -343,7 +369,7 @@ export default class Input extends Component {
onValidate,
});
- const isShowClearIcon = ((clearable && this.value && !disabled) || showClearIconOnEmpty) && this.isHover;
+ const isShowClearIcon = ((clearable && this.innerValue && !disabled) || showClearIconOnEmpty) && this.isHover;
const prefixIconContent = prefixIcon
? renderIcon(
@@ -403,8 +429,8 @@ export default class Input extends Component {
}
const suffixIconContent = renderIcon('t', 'suffix', parseTNode(convertToLightDomNode(suffixIconNew)));
- const labelContent = isFunction(label) ? (label as any)() : label;
- const suffixContent = isFunction(suffix) ? (suffix as any)() : suffix;
+ const labelContent = isFunction(label) ? label({}) : label;
+ const suffixContent = isFunction(suffix) ? suffix({}) : suffix;
const limitNumberNode =
limitNumber() && showLimitNumber ? (
@@ -417,7 +443,7 @@ export default class Input extends Component {
) : null;
- const innerValue = this.composingRef.current ? this.composingValue : this.value ?? '';
+ const innerValue = this.composingRef.current ? this.composingValue : this.innerValue ?? '';
const formatDisplayValue = format && !this.isFocused ? format(innerValue) : innerValue;
const renderInput = (