Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(input): fix input 受控 #147

Merged
merged 1 commit into from
Sep 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions src/input/_example/align.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@ import 'tdesign-web-components/space';
import { Component } from 'omi';

export default class InputAlign extends Component {
inputValue = '';

render() {
return (
<t-space direction="vertical" style={{ width: '100%' }}>
Expand Down
1 change: 1 addition & 0 deletions src/input/_example/auto-width.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export default class InputAutowidth extends Component {
defaultValue="宽度自适应"
onChange={(value) => {
this.inputValue = value;
this.update();
}}
/>
</div>
Expand Down
2 changes: 2 additions & 0 deletions src/input/_example/base.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export default class InputBase extends Component {
placeholder="请输入内容(无默认值)"
onChange={(value) => {
this.value1 = value;
this.update();
console.log('change', value);
}}
onFocus={() => {
Expand All @@ -30,6 +31,7 @@ export default class InputBase extends Component {
onChange={(value) => {
console.log(value);
this.value2 = value;
this.update();
}}
onEnter={(value) => {
console.log(value);
Expand Down
2 changes: 2 additions & 0 deletions src/input/_example/borderless.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export default class InputBase extends Component {
placeholder="请输入内容(无默认值)"
onChange={(value) => {
this.value1 = value;
this.update();
console.log(value);
}}
/>
Expand All @@ -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);
Expand Down
12 changes: 10 additions & 2 deletions src/input/_example/clearable.tsx
Original file line number Diff line number Diff line change
@@ -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';

Expand All @@ -10,7 +10,15 @@ export default class InputBase extends Component {
render() {
return (
<t-space direction="vertical">
<t-input value={this.value1} placeholder="请输入" clearable />
<t-input
value={this.value1}
placeholder="请输入"
onChange={(value) => {
this.value1 = value;
this.update();
}}
clearable
/>
</t-space>
);
}
Expand Down
1 change: 1 addition & 0 deletions src/input/_example/format.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export default class InputForMat extends Component {
value={this.inputValue}
onChange={(value) => {
this.inputValue = value;
this.update();
}}
status={inputStatus}
format={format}
Expand Down
24 changes: 21 additions & 3 deletions src/input/_example/password.tsx
Original file line number Diff line number Diff line change
@@ -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';

Expand All @@ -12,8 +12,26 @@ export default class InputBase extends Component {
render() {
return (
<t-space direction="vertical">
<t-input value={this.value1} placeholder="请输入密码" type="password" prefixIcon={<t-icon-lock-on />} />
<t-input value={this.value2} placeholder="请输入密码" type="password" prefixIcon={<t-icon-lock-on />} />
<t-input
value={this.value1}
placeholder="请输入密码"
type="password"
prefixIcon={<t-icon-lock-on />}
onChange={(value) => {
this.value1 = value;
this.update();
}}
/>
<t-input
value={this.value2}
placeholder="请输入密码"
type="password"
prefixIcon={<t-icon-lock-on />}
onChange={(value) => {
this.value2 = value;
this.update();
}}
/>
</t-space>
);
}
Expand Down
9 changes: 9 additions & 0 deletions src/input/_example/status.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export default class InputStatus extends Component {
value={this.inputValue}
onChange={(value) => {
this.inputValue = value;
this.update();
}}
/>
<t-input
Expand All @@ -26,6 +27,7 @@ export default class InputStatus extends Component {
value={this.inputValue}
onChange={(value) => {
this.inputValue = value;
this.update();
}}
/>
</t-space>
Expand All @@ -35,6 +37,7 @@ export default class InputStatus extends Component {
value={this.inputValue}
onChange={(value) => {
this.inputValue = value;
this.update();
}}
status="success"
/>
Expand All @@ -43,6 +46,7 @@ export default class InputStatus extends Component {
value={this.inputValue}
onChange={(value) => {
this.inputValue = value;
this.update();
}}
status="warning"
/>
Expand All @@ -51,6 +55,7 @@ export default class InputStatus extends Component {
value={this.inputValue}
onChange={(value) => {
this.inputValue = value;
this.update();
}}
status="error"
/>
Expand All @@ -62,6 +67,7 @@ export default class InputStatus extends Component {
value={this.inputValue}
onChange={(value) => {
this.inputValue = value;
this.update();
}}
/>
<t-input
Expand All @@ -70,6 +76,7 @@ export default class InputStatus extends Component {
value={this.inputValue}
onChange={(value) => {
this.inputValue = value;
this.update();
}}
status="success"
/>
Expand All @@ -79,6 +86,7 @@ export default class InputStatus extends Component {
value={this.inputValue}
onChange={(value) => {
this.inputValue = value;
this.update();
}}
status="warning"
/>
Expand All @@ -88,6 +96,7 @@ export default class InputStatus extends Component {
value={this.inputValue}
onChange={(value) => {
this.inputValue = value;
this.update();
}}
status="error"
/>
Expand Down
54 changes: 40 additions & 14 deletions src/input/input.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ export default class Input extends Component<InputProps> {

composingRef = createRef();

value;
innerValue;

composingValue = '';

Expand All @@ -103,6 +103,10 @@ export default class Input extends Component<InputProps> {

eventProps;

private get isControlled() {
return Reflect.has(this.props, 'value');
}

private handlePasswordVisible = (e: MouseEvent) => {
e.stopImmediatePropagation();
if (this.props.disabled) return;
Expand All @@ -116,7 +120,7 @@ export default class Input extends Component<InputProps> {
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,
Expand All @@ -134,7 +138,9 @@ export default class Input extends Component<InputProps> {
// 完成中文输入时同步一次 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,
Expand Down Expand Up @@ -189,7 +195,6 @@ export default class Input extends Component<InputProps> {
private handleClear = (e: MouseEvent) => {
const { onChange, onClear } = this.props;
this.composingValue = '';
this.value = '';
this.update();
onChange?.('', { e });
onClear?.({ e });
Expand All @@ -198,20 +203,27 @@ export default class Input extends Component<InputProps> {
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) => {
Expand Down Expand Up @@ -245,7 +257,7 @@ export default class Input extends Component<InputProps> {
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;
}

Expand All @@ -270,17 +282,22 @@ export default class Input extends Component<InputProps> {
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,
allowInputOverMax: this.props.allowInputOverMax,
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) {
Expand All @@ -290,6 +307,15 @@ export default class Input extends Component<InputProps> {
});
}

receiveProps(props: InputProps | OmiProps<InputProps, any>, oldProps: InputProps | OmiProps<InputProps, any>) {
if (
(this.isControlled && props.value !== oldProps.value) ||
(Reflect.has(oldProps, 'value') && !this.isControlled)
) {
this.innerValue = props.value;
}
}

render(props: OmiProps<InputProps>) {
const {
autoWidth,
Expand Down Expand Up @@ -322,15 +348,15 @@ export default class Input extends Component<InputProps> {
} = props;

const { limitNumber, tStatus } = useLengthLimit({
value: this.value === undefined ? undefined : String(this.value),
value: this.innerValue === undefined ? undefined : String(this.innerValue),
status,
maxlength,
maxcharacter,
allowInputOverMax,
onValidate,
});

const isShowClearIcon = ((clearable && this.value && !disabled) || showClearIconOnEmpty) && this.isHover;
const isShowClearIcon = ((clearable && this.innerValue && !disabled) || showClearIconOnEmpty) && this.isHover;

const prefixIconContent = prefixIcon
? renderIcon(
Expand Down Expand Up @@ -390,8 +416,8 @@ export default class Input extends Component<InputProps> {
}

const suffixIconContent = renderIcon('t', 'suffix', parseTNode(convertToLightDomNode(suffixIconNew)));
const labelContent = isFunction(label) ? label() : label;
const suffixContent = isFunction(suffix) ? suffix() : suffix;
const labelContent = isFunction(label) ? label({}) : label;
const suffixContent = isFunction(suffix) ? suffix({}) : suffix;

const limitNumberNode =
limitNumber() && showLimitNumber ? (
Expand All @@ -404,7 +430,7 @@ export default class Input extends Component<InputProps> {
</div>
) : 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 = (
<input
Expand Down
Loading