在 React 中使用单个 onChange 处理程序处理多个输入
介绍
使用React组件创建表单时,通常使用onChange处理程序来监听输入元素的变化并记录其状态值。除了只处理一个输入外,还可以设置一个onChange处理程序来处理表单中的许多不同输入。
单一输入
onChange处理程序将监听输入的任何更改,并在值更改时触发事件。使用这样的文本输入字段,我们可以传递onChange prop:
<label>
First name
<input
type="text"
onChange={handleChange}
/>
</label>
prop 的值是 handleChange 函数;它是一个事件处理程序。处理程序作为参数接收的事件是一个包含target字段的对象。此target是事件处理程序绑定到的 DOM 元素(即文本输入字段)。通过访问此字段,我们可以确定 target的值更改为:
function handleChange(evt) {
console.log("new value", evt.target.value);
}
该处理程序将简单地打印文本输入改变后的新值。
受控组件
但到目前为止,这个变更处理程序还没什么用。相反,我们可以设想变更处理程序应该监听变更并将新的变更保存在内部状态中,以便以后提交表单。
为了实现这一点,通常将输入字段设置为受控组件,这意味着 React 状态在 UI 中驱动其值。为此,我们将添加一些 React 状态并使用它来设置输入字段的值:
import React from "react";
function Form() {
const [state, setState] = React.useState({
firstName: ""
})
return (
<form>
<label>
First name
<input
type="text"
value={state.firstName}
onChange={handleChange}
/>
</label>
</form>
);
}
然后我们将使用setState函数使handleChange函数更新状态:
function handleChange(evt) {
setState({ firstName: evt.target.value });
}
现在我们有一个可捕获更改并相应更新状态的受控组件。这是单个输入的工作示例。
多个输入
如果我们添加另一个输入框会怎么样?除了名字字段,我们还添加姓氏字段作为第二个文本输入字段:
import React from "react";
function Form() {
const [state, setState] = React.useState({
firstName: "",
lastName: ""
})
return (
<form>
<label>
First name
<input
type="text"
name="firstName"
value={state.firstName}
onChange={handleChange}
/>
</label>
<label>
Last name
<input
type="text"
name="lastName"
value={state.lastName}
onChange={handleChange}
/>
</label>
</form>
);
}
除了新的输入字段外,还进行了几个重大更改。已将新的lastName字符串添加到状态以存储来自此输入的数据,并且每个输入元素都有一个新的name属性。这些name属性将作为输入 HTML 元素上的名称属性显示在 DOM 中。我们将在对处理程序代码的调整中使用它们:
function handleChange(evt) {
const value = evt.target.value;
setState({
...state,
[evt.target.name]: value
});
}
除了从事件目标获取值之外,我们还会获取该目标的名称。这是使用一个处理程序处理多个输入字段的关键点。我们将所有更改都集中到该处理程序中,然后使用名称区分更改来自哪个输入。
此示例使用[evt.target.name](名称放在方括号中)在对象中创建动态键名。由于表单名称属性与状态属性键匹配,因此firstName输入将设置firstName状态,而lastName输入将分别设置lastName状态。
还要注意,因为我们使用的是包含多个属性的单个状态对象,所以在调用setState时,我们会将现有状态展开(...state)回新状态值,并手动合并。在解决方案中使用React.useState时,这是必需的。
文本区域输入
React 规范了许多其他类型的输入字段的使用,以便以非常相似的方式使用它们。但这里我们将介绍一些差异。我们不必每次都重写整个示例,而是只查看与所讨论的输入类型相关的输入元素和状态的子集。
textarea输入的功能与<input type="text" /> 完全相同,并且handleChange` 保持不变:
import React from "react";
function Form() {
const [state, setState] = React.useState({
bio: ""
})
return (
<form>
<label>
Bio
<textarea name="bio" value={state.bio} onChange={handleChange} />
</label>
</form>
);
}
选择输入
除了 DOM 结构定义略有不同之外,select元素在发布更改和使用值的方式上是相同的:
import React from "react";
function Form() {
const [state, setState] = React.useState({
version: "16.8"
})
return (
<form>
<label>
Favorite version
<select name="version" onChange={handleChange} value={state.version}>
<option value="16.8">v16.8.0</option>
<option value="16.7">v16.7.0</option>
<option value="16.6">v16.6.0</option>
<option value="16.5">v16.5.0</option>
</select>
</label>
</form>
);
}
请注意,当前选定的值是通过父级select元素上的value属性设置的。初始选定的值由初始state.version值设置。子级option元素上的value属性是可能被更改为的值。
广播输入
<input type="radio" /> 的功能与其他输入略有不同。它的value属性是静态的,表示要选择的选项。名称是重复的,并且必须与组成单选按钮组的单选按钮相匹配。checked属性引入了一个条件,该条件确定该特定按钮是否显示为活动状态。
import React from "react";
function Form() {
const [state, setState] = React.useState({
level: "master"
})
return (
<form>
<div>
Level
<label>
Acolyte
<input
type="radio"
name="level"
value="acolyte"
checked={state.level === "acolyte"}
onChange={handleChange}
/>
</label>
<label>
Master
<input
type="radio"
name="level"
value="master"
checked={state.level === "master"}
onChange={handleChange}
/>
</label>
</div>
</form>
);
}
复选框输入
<input type="checkbox" />元素看起来有点像单选按钮,因为它利用了checked属性。但复选框是独立的控件,不存在于组中,因此它们像大多数其他输入一样具有唯一的name属性:
import React from "react";
function Form() {
const [state, setState] = React.useState({
hooks: true
})
return (
<form>
<label>
With hooks
<input
type="checkbox"
name="hooks"
checked={state.hooks}
onChange={handleChange}
/>
</label>
</form>
);
}
复选框需要进行一项重要的更改,即对handleChange函数进行调整:
function handleChange(evt) {
const value =
evt.target.type === "checkbox" ? evt.target.checked : evt.target.value;
setState({
...state,
[evt.target.name]: value
});
}
免责声明:本内容来源于第三方作者授权、网友推荐或互联网整理,旨在为广大用户提供学习与参考之用。所有文本和图片版权归原创网站或作者本人所有,其观点并不代表本站立场。如有任何版权侵犯或转载不当之情况,请与我们取得联系,我们将尽快进行相关处理与修改。感谢您的理解与支持!
请先 登录后发表评论 ~