受控组件
- input 可以设置
value或checked属性 - 可以监听
onChange事件,更新 state
const NoteSection: React.FC = () => {
const [note, setNote] = useState('')
return (
<label>
<span>备注</span>
<input type="text" placeholder="在这里添加备注"
value={ note }
onChange={ (e)=> setNode(e.target.value) }
/>
</label>
)
}
以上更新 state 的流程:
- 可以通过初始 state 中设置表单的默认值
- 每当表单的值发生变化时,调用 onChange 事件处理器
- 事件处理器通过事件对象 e 拿到改变后的状态,并更新组件的 state
- 一旦通过 setState 方法更新state,就会触发视图的重新渲染,完成表单组件的更新
缺陷:
表单元素的值都是由 React 组件进行管理,当有多个输入框,或者多个这种组件时,如果想同时获取到全部的值就必须每个都要编写事件处理函数,这会让代码看着很臃肿,所以为了解决这种情况,出现了非受控组件。
非受控组件
非受控模式:
- 你中间的过程我不想控制,结束的时候我通过 ref 从 DOM 获得表单最新值。
- 不用为每个状态更新编写一个事件处理程序。
- 一个表单组件没有 value props(单选和复选按钮对应的是 checked props )
const NoteSection: React.FC = () => {
const [note, setNote] = useState('')
// 当用户的鼠标移出 input 的时候,就调用 x
const x = () => {
// 这个 x 怎么获取到最新的 note 值呢?
// 直接读 note 是不行的,因为现在 input 根本就没有把 note 的最新值传给 note
// 只能去获取 input 的 value!
}
return (
<label>
<span>备注</span>
<input type="text" placeholder="在这里添加备注"
defaultValue={note}
onBlur={x}
/>
</label>
)
}
const NoteSection: React.FC = () => {
// useState 钩子把初始状态作为一个参数,所以 note 状态变量将被初始化为默认值
const [note, setNote] = useState('')
const refInput = useRef<HTMLInputElement>(null)
const onBlur = () => {
if (refInput.current !== null) {
setNote(refInput.current.value)
}
}
return (
<label>
<span>备注</span>
{ /*
当使用非受控组件时,提前创建好 ref 对象 refInput,
将创建出来的对象绑定到 input 元素, 我们使用 ref 来访问输入,从 DOM 节点中获取表单数据
如果你用 ref = { refInput } 向 React 传递一个可变的 ref 对象,这个对象就是 refInput
React就会将其 .current 属性 设置为相应的 DOM 节点,只要该节点发生变化
要为一个不受控制的输入字段设置一个默认值,请在该字段上设置 defaultValue
你可以用 defaultValue 给一个不受控制的输入 传递一个初始值
把 note 作为初始值传给 defaultValue 作为默认值
*/ }
<input
type="text"
placeholder="在这里添加备注"
ref={ refInput }
defaultValue={ note }
onBlur={ onBlur }
/>
</label>
)
}
总结
- 同时设置
value和defaultValue是不允许的 - 非受控组件上
defaultValue不是必须的,可以省略 - 在一个非受控组件(一个没有
onChange处理程序的输入字段)上设置value,这将使输入字段变得不可改变,你将无法在其中打字。 - 非受控模式使用场景:你中间的过程我不想控制,结束的时候我通过
ref去读取最新的值。 - 页面中所有输入类的 DOM 如果是现用现取的称为非受控组件,而通过 setState 将输入的值维护到了 state 中,需要时再从 state 中取出,这里的数据就受到了 state 的控制,称为受控组件。