React 中非受控和受控的组件
两者都是呈现 HTML 表单元素的 React 组件。这意味着,每当您创建具有 HTML 表单的组件时,您都会创建两个组件中的任何一个。但是两者之间的显着差异,接下来我们来我们来详细介绍它们。
受控的组件
在 HTML 中,表单元素(如<input>
、 <textarea>
和 <select>
)通常自己维护 state,并根据用户输入进行更新。而在 React 中,可变状态(mutable state)通常保存在组件的 state 属性中,并且只能通过使用 setState()
来更新。
我们可以把两者结合起来,使 React 的 state 成为“唯一数据源”。渲染表单的 React 组件还控制着用户输入过程中表单发生的操作。被 React 以这种方式控制取值的表单输入元素就叫做“受控组件”。
让我们看以下示例以更好地理解此概念。
import { useState } from "react"; const TextInputControlled = () => { const [name, setName] = useState(""); return ( <div> <input type="text" placeholder="Type... (Controlled)" value={name} onChange={(event) => { console.log(event.target.value); setName(event.target.value); }} /> </div> ); };
在上面的函数组件中,我们调用了状态,并且可以在方法的帮助下对其进行更改。该组件将返回带有事件的输入字段,该事件正在记录输入字段值,并使用该方法将名称设置为新的输入值。
对于受控组件来说,输入的值始终由 React 的 state 驱动。你也可以将 value 传递给其他 UI 元素,或者通过其他事件处理函数重置,但这意味着你需要编写更多的代码。
然而当有多个输入框,或者多个这种组件时,如果想同时获取到全部的值就必须每个都要编写事件处理函数,这会让代码看着很臃肿,所以为了解决这种情况,出现了非受控组件。
这个时候我们更推荐使用非受控组件。
非受控的组件
不受控制的组件是呈现表单元素并在 DOM 本身中更新其值的组件。可以使用 ref 而不是为每个状态更新编写事件处理程序,以便从 DOM 访问表单值。集成具有不受控制组件的 React 和非 React 代码更容易,因为不受控制的组件在 DOM 中维护其事实来源。如果您希望代码数量快速而粗糙,则代码数量也会略有减少。
「默认值」
在 React 的渲染生命周期中,DOM 中的值将被表单元素上的 value 属性覆盖。通过使用不受控制的组件,您可能希望 React 设置初始值,但保持后续更新不变。在这种情况下, 你可以指定一个 defaultValue
属性,而不是 value
。在一个组件已经挂载之后去更新 defaultValue
属性的值,不会造成 DOM 上值的任何更新。
让我们看下面的例子,
import { useRef } from "react"; const App = () => { const inputRef = useRef(null); const handleSubmit = () => { console.log(inputRef.current.value); }; return ( <div> <input type="text" defaultValue="Type..." ref={inputRef} /> <button onClick={handleSubmit}>Submit</button> </div> ); }; export default App;
在上面的示例中,我们使用了一个调用,并将其附加到使用属性的元素。单击提交按钮时,其值将记录在控制台中。
同样,<input type="checkbox">
和 <input type="radio">
支持 defaultChecked
,<select>
和 <textarea>
支持 defaultValue
。
「文件输入标记」
<input type="file" ref={this.fileInput} />
元素始终是不受控制的组件,因为它的值不能以编程方式设置,而只能由用户设置。<input type="file" />
不受控制组件的限制
- 无即时字段验证
- 无法有条件地禁用提交按钮
- 无法强制执行输入格式
- 单个数据没有多个输入
- 无动态输入
小结
总体而言,非受控组件可以在必要时使用或比受控组件更有效,否则,尽可能使用受控组件。若要使用非受控制的组件,可以使用 ref 直接访问 DOM 值。对于受控组件,我们将表单数据值存储在 React 组件的状态属性中。在了解了“非受控制”和“受控”组件之后,很明显,“受控”组件绝对推荐使用“而不是”非受控制“组件,但”非受控制“组件有时也是必不可少的,因此,了解两者是件好事。