赞
踩
2021SC@SDUSC
通过鼠标或键盘输入内容,是最基础的表单域的包装。
用法:
需要用户输入表单域内容时。
提供组合型输入框,带搜索的输入框,还可以进行大小选择。
参数 | 说明 | 类型 | 默认值 | 版本 |
---|---|---|---|---|
addonAfter | 带标签的 input,设置后置标签 | ReactNode | - | |
addonBefore | 带标签的 input,设置前置标签 | ReactNode | - | |
allowClear | 可以点击清除图标删除内容 | boolean | - | |
bordered | 是否有边框 | boolean | true | 4.5.0 |
defaultValue | 输入框默认内容 | string | - | |
disabled | 是否禁用状态,默认为 false | boolean | false | |
id | 输入框的 id | string | - | |
maxLength | 最大长度 | number | - | |
prefix | 带有前缀图标的 input | ReactNode | - | |
size | 控件大小。注:标准表单内的输入框大小限制为 large | large | middle | small | - | |
suffix | 带有后缀图标的 input | ReactNode | - | |
type | 声明 input 类型,同原生 input 标签的 type 属性,见:MDN(请直接使用 Input.TextArea 代替 type="textarea" ) | string | text | |
value | 输入框内容 | string | - | |
onChange | 输入框内容变化时的回调 | function(e) | - | |
onPressEnter | 按下回车的回调 | function(e) | - |
参数 | 说明 | 类型 | 默认值 |
---|---|---|---|
compact | 是否用紧凑模式 | boolean | false |
size | Input.Group 中所有的 Input 的大小,可选 large default small | string | default |
<Input.Group>
<input />
<input />
</Input.Group>
名称 | 说明 | 参数 | 版本 |
---|---|---|---|
blur | 取消焦点 | - | |
focus | 获取焦点 | (option?: { preventScroll?: boolean, cursor?: ‘start’ | ‘end’ | ‘all’ }) | option - 4.10.0 |
export interface InputFocusOptions extends FocusOptions {
cursor?: 'start' | 'end' | 'all';
}
cursor属性用于规定要显示的光标的类型
export interface InputProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'size' | 'prefix' | 'type'> { prefixCls?: string; size?: SizeType; // ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#%3Cinput%3E_types type?: LiteralUnion< | 'button' | 'checkbox' | 'color' | 'date' | 'datetime-local' | 'email' | 'file' | 'hidden' | 'image' | 'month' | 'number' | 'password' | 'radio' | 'range' | 'reset' | 'search' | 'submit' | 'tel' | 'text' | 'time' | 'url' | 'week', string >; onPressEnter?: React.KeyboardEventHandler<HTMLInputElement>; addonBefore?: React.ReactNode; addonAfter?: React.ReactNode; prefix?: React.ReactNode; suffix?: React.ReactNode; allowClear?: boolean; bordered?: boolean; htmlSize?: number; }
运用了联合类型,将所需的全部类型囊括其中
export function resolveOnChange<E extends HTMLInputElement | HTMLTextAreaElement>( target: E, e: | React.ChangeEvent<E> | React.MouseEvent<HTMLElement, MouseEvent> | React.CompositionEvent<HTMLElement>, onChange: undefined | ((event: React.ChangeEvent<E>) => void), targetValue?: string, ) { if (!onChange) { return; } let event = e; if (e.type === 'click') { // click clear icon event = Object.create(e); // Clone a new target for event. // Avoid the following usage, the setQuery method gets the original value. // // const [query, setQuery] = React.useState(''); // <Input // allowClear // value={query} // onChange={(e)=> { // setQuery((prevStatus) => e.target.value); // }} // /> const currentTarget = target.cloneNode(true) as E; event.target = currentTarget; event.currentTarget = currentTarget; currentTarget.value = ''; onChange(event as React.ChangeEvent<E>); return; } // Trigger by composition event, this means we need force change the input value if (targetValue !== undefined) { event = Object.create(e); event.target = target; event.currentTarget = target; target.value = targetValue; onChange(event as React.ChangeEvent<E>); return; } onChange(event as React.ChangeEvent<E>); }
用于处理输入框内容变化时的回调
export function triggerFocus( element?: HTMLInputElement | HTMLTextAreaElement, option?: InputFocusOptions, ) { if (!element) return; element.focus(option); // Selection content const { cursor } = option || {}; if (cursor) { const len = element.value.length; switch (cursor) { case 'start': element.setSelectionRange(0, 0); break; case 'end': element.setSelectionRange(len, len); break; default: element.setSelectionRange(0, len); } } }
点击聚焦的实现
class Input extends React.Component<InputProps, InputState> { static Group: typeof Group; static Search: typeof Search; static TextArea: typeof TextArea; static Password: typeof Password; static defaultProps = { type: 'text', }; input!: HTMLInputElement; clearableInput!: ClearableLabeledInput; removePasswordTimeout: any; direction: DirectionType = 'ltr'; constructor(props: InputProps) { super(props); const value = typeof props.value === 'undefined' ? props.defaultValue : props.value; this.state = { value, focused: false, // eslint-disable-next-line react/no-unused-state prevValue: props.value, }; } static getDerivedStateFromProps(nextProps: InputProps, { prevValue }: InputState) { const newState: Partial<InputState> = { prevValue: nextProps.value }; if (nextProps.value !== undefined || prevValue !== nextProps.value) { newState.value = nextProps.value; } return newState; } componentDidMount() { this.clearPasswordValueAttribute(); } // Since polyfill `getSnapshotBeforeUpdate` need work with `componentDidUpdate`. // We keep an empty function here. componentDidUpdate() {} getSnapshotBeforeUpdate(prevProps: InputProps) { if (hasPrefixSuffix(prevProps) !== hasPrefixSuffix(this.props)) { devWarning( this.input !== document.activeElement, 'Input', `When Input is focused, dynamic add or remove prefix / suffix will make it lose focus caused by dom structure change. Read more: https://ant.design/components/input/#FAQ`, ); } return null; } componentWillUnmount() { if (this.removePasswordTimeout) { clearTimeout(this.removePasswordTimeout); } } focus = (option?: InputFocusOptions) => { triggerFocus(this.input, option); }; blur() { this.input.blur(); } setSelectionRange(start: number, end: number, direction?: 'forward' | 'backward' | 'none') { this.input.setSelectionRange(start, end, direction); } select() { this.input.select(); } saveClearableInput = (input: ClearableLabeledInput) => { this.clearableInput = input; }; saveInput = (input: HTMLInputElement) => { this.input = input; }; onFocus: React.FocusEventHandler<HTMLInputElement> = e => { const { onFocus } = this.props; this.setState({ focused: true }, this.clearPasswordValueAttribute); onFocus?.(e); }; onBlur: React.FocusEventHandler<HTMLInputElement> = e => { const { onBlur } = this.props; this.setState({ focused: false }, this.clearPasswordValueAttribute); onBlur?.(e); }; setValue(value: string, callback?: () => void) { if (this.props.value === undefined) { this.setState({ value }, callback); } else { callback?.(); } } handleReset = (e: React.MouseEvent<HTMLElement, MouseEvent>) => { this.setValue('', () => { this.focus(); }); resolveOnChange(this.input, e, this.props.onChange); }; renderInput = ( prefixCls: string, size: SizeType | undefined, bordered: boolean, input: ConfigConsumerProps['input'] = {}, ) => { const { className, addonBefore, addonAfter, size: customizeSize, disabled, htmlSize, } = this.props; // Fix https://fb.me/react-unknown-prop const otherProps = omit(this.props as InputProps & { inputType: any }, [ 'prefixCls', 'onPressEnter', 'addonBefore', 'addonAfter', 'prefix', 'suffix', 'allowClear', // Input elements must be either controlled or uncontrolled, // specify either the value prop, or the defaultValue prop, but not both. 'defaultValue', 'size', 'inputType', 'bordered', 'htmlSize', ]); return ( <input autoComplete={input.autoComplete} {...otherProps} onChange={this.handleChange} onFocus={this.onFocus} onBlur={this.onBlur} onKeyDown={this.handleKeyDown} className={classNames( getInputClassName(prefixCls, bordered, customizeSize || size, disabled, this.direction), { [className!]: className && !addonBefore && !addonAfter, }, )} ref={this.saveInput} size={htmlSize} /> ); }; clearPasswordValueAttribute = () => { // https://github.com/ant-design/ant-design/issues/20541 this.removePasswordTimeout = setTimeout(() => { if ( this.input && this.input.getAttribute('type') === 'password' && this.input.hasAttribute('value') ) { this.input.removeAttribute('value'); } }); }; handleChange = (e: React.ChangeEvent<HTMLInputElement>) => { this.setValue(e.target.value, this.clearPasswordValueAttribute); resolveOnChange(this.input, e, this.props.onChange); }; handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => { const { onPressEnter, onKeyDown } = this.props; if (onPressEnter && e.keyCode === 13) { onPressEnter(e); } onKeyDown?.(e); }; renderComponent = ({ getPrefixCls, direction, input }: ConfigConsumerProps) => { const { value, focused } = this.state; const { prefixCls: customizePrefixCls, bordered = true } = this.props; const prefixCls = getPrefixCls('input', customizePrefixCls); this.direction = direction; return ( <SizeContext.Consumer> {size => ( <ClearableLabeledInput size={size} {...this.props} prefixCls={prefixCls} inputType="input" value={fixControlledValue(value)} element={this.renderInput(prefixCls, size, bordered, input)} handleReset={this.handleReset} ref={this.saveClearableInput} direction={direction} focused={focused} triggerFocus={this.focus} bordered={bordered} /> )} </SizeContext.Consumer> ); }; render() { return <ConfigConsumer>{this.renderComponent}</ConfigConsumer>; } }
Input类
其中可以看到react生命周期中的各部分
constructor
getDerivedStateFromProps 将传入的props映射到state上
componentWillmount componentDidMount
render等
其中还包括对聚焦失焦、摁键的处理方法
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。