【antd】输入控件的思想

antd对于form中输入控件的抽象十分简单,只要能接收value和onChange属性的组件都可以成为Form.Item的子组件,为Form对应的字段提供值。对于输入控件的抽象我认为这已经达到了极致,事件(onChange)产生值(value)。事件向上,值向下,完全符合React哲学。

如何实现一个标准的输入组件?

对于输入组件首先需要具备接收value和onChange属性的能力,这两个属性被提供的情况下这个组件被称为受控组件,它受到父组件控制,状态来自父组件。当父组件没有提供value的情况下该组件是非受控组件,有自己的状态。

是否受控主要取决于value属性是否提供,因为value决定了组件当前的状态,当前状态被父组件控制,所以称之为受控组件。

输入组件的状态是会改变的,最常见的方式就是来自用户行为,例如在input中输入内容,该组件的状态(value)就会改变。

  1. 因为组件可以作为非受控组件,所以组件自身有innerValue和setInnerValue用于展示和响应用户输入。
  2. 如果父组件没有提供value
    1. 组件使用自身的setInnerValue响应用户输入,改变自身状态innerValue
    2. 如果父组件提供onChange,在setInnerValue同时触发onChange事件通知父组件
  3. 如果父组件提供了value,组件失去了决定自身状态的能力(自身不会直接响应用户输入)
    1. 如果父组件提供onChange函数,则使用该函数响应用户输入
    2. 组件自身的setInnerValue不会响应用户输入(setInnerValue的作用是修改innerValue,因为有父组件的value,innerValue会响应value的变化,所以setInnerValue不应该直接修改innerValue导致其和value不一致)
function Input (props) {
    
    
	const [innerValue, setInnerValue] = useState(props.value);

	useEffect(() => {
    
    
		if ('value' in props) setInnerValue(props.value)
	}, [props.value])

	function handleChange (ev) {
    
    
		if (!('value' in props)) {
    
    
			setInnerValue(ev.target.value)
		}

		props.onChange?.(ev.target.value)
	}
	
	return <input value={
    
    innerValue} onChange={
    
    handleChange} />
}

Guess you like

Origin blog.csdn.net/letterTiger/article/details/121590975