ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
# 表单 HTML 表单元素跟 React 中的其它 DOM 元素运作有所不同,因为表单元素本身会保留一些内部的状态。例如,这个纯 HTML 表单接受一个单独的 name: ~~~ <form> <label> Name: <input type="text" name="name" /> </label> <input type="submit" value="Submit" /> </form> ~~~ 这个表单在用户提交的时候具有默认的导航到一个新页面的 HTML 表单行为。如果你希望 React 中保持这个行为,也可以工作。但是多数情况下,用一个处理表单提交并访问用户输入到表单中的数据的 JavaScript 函数也非常边界。标准的方式是使用一个叫做“控制组件”的技术。 ## 控制组件 在 HTML 中,表单元素如 `<input>`、`<textare>` 和 `<select>` 一般基于用户的输入维护并更新它们自己的状态。在 React 中, 可变状态一般保存在组件的 state 属性中,并且只能通过 [setState()](https://facebook.github.io/react/docs/react-component.html#setstate) 更新。 我们可以通过使 React 的 state 成为“单一源”来结合这两个形式。然后渲染表单的 React 组件也可以控制在用户输入之后的行为。被 React 以这种形式控制值的输入表单元素,称为一个“控制组件”。 例如,如果我们希望使前一个例子在被提交的时候打印 name,我们可以编写它为一个控制组件: ~~~ class NameForm extends React.Component { constructor(props) { super(props); this.state = {value: ''}; this.handleChange = this.handleChange.bind(this); this.handleSubmit = this.handleSubmit.bind(this); } handleChange(event) { this.setState({value: event.target.value}); } handleSubmit(event) { alert('A name was submitted: ' + this.state.value); event.preventDefault(); } render() { return ( <form onSubmit={this.handleSubmit}> <label> Name: <input type="text" value={this.state.value} onChange={this.handleChange} /> </label> <input type="submit" value="Submit" /> </form> ); } } ~~~ 在 CodePen 中[打开查看](https://codepen.io/gaearon/pen/VmmPgp?editors=0010)。 由于 value 属性设置在我们的表单元素上,显示的值总是 this.state.value,使 React state 是实际的源。由于 handleChange 在每个击键运行以更新 React 的状态,显示的值将更新为用户的输入。 通过一个控制组件,每个状态变化都有一个相关的处理函数。这使它可以简单的修改或者验证用户输入。例如,如果我们希望确保 name 使用全部大写字母,我们可以编写 handleChange 为: ~~~ handleChange(event) { this.setState({value: event.target.value.toUpperCase()}); } ~~~ ## textare 标签 在 HTML 中,`<textarea> `元素通过它的子节点定义了它的文本: ~~~ <textarea> Hello there, this is some text in a text area </textarea> ~~~ 在 React 中,`<textarea>` 使用一个 value 属性替代。这个方式,使用了 `<textarea>` 的表单可以被编写为和使用一个单行输入框的表单非常相似: ~~~ class EssayForm extends React.Component { constructor(props) { super(props); this.state = { value: 'Please write an essay about your favorite DOM element.' }; this.handleChange = this.handleChange.bind(this); this.handleSubmit = this.handleSubmit.bind(this); } handleChange(event) { this.setState({value: event.target.value}); } handleSubmit(event) { alert('An essay was submitted: ' + this.state.value); event.preventDefault(); } render() { return ( <form onSubmit={this.handleSubmit}> <label> Name: <textarea value={this.state.value} onChange={this.handleChange} /> </label> <input type="submit" value="Submit" /> </form> ); } } ~~~ 注意,this.state.value 在构造函数中初始化,所以文本域开始的时候带有一些文本。 ## select 标签 在 HTML 中,`<select>` 创建了一个下拉列表。例如,这段 HTML 创建一个一个口味列表: ~~~ <select> <option value="grapefruit">Grapefruit</option> <option value="lime">Lime</option> <option selected value="coconut">Coconut</option> <option value="mango">Mango</option> </select> ~~~ 注意,Coconut 选项是初始化被选中的,因为它的 selected 属性。React 中,并不使用这个 selected 属性,而是在根 select 标签中使用了一个 value 属性。这在一个控制组件中是更方便的,因为你只需要在一处更新它即可。例如: ~~~ class FlavorForm extends React.Component { constructor(props) { super(props); this.state = {value: 'coconut'}; this.handleChange = this.handleChange.bind(this); this.handleSubmit = this.handleSubmit.bind(this); } handleChange(event) { this.setState({value: event.target.value}); } handleSubmit(event) { alert('Your favorite flavor is: ' + this.state.value); event.preventDefault(); } render() { return ( <form onSubmit={this.handleSubmit}> <label> Pick your favorite La Croix flavor: <select value={this.state.value} onChange={this.handleChange}> <option value="grapefruit">Grapefruit</option> <option value="lime">Lime</option> <option value="coconut">Coconut</option> <option value="mango">Mango</option> </select> </label> <input type="submit" value="Submit" /> </form> ); } } ~~~ 在 CodePen 中[打开查看](https://codepen.io/gaearon/pen/JbbEzX?editors=0010)。 总的来说,这使 `<input type="text">`, `<textarea>` 和 `<select>` 都以类似的方式工作 —— 它们都接受一个 value 属性可以用来实现一个控制组件。 ## 替代控制组件 可能有时候使用控制组件是单调的,因为你需要编写一个事件处理程序对于每个可修改的数据,并在一个 React 组件中传递所有的输入状态。这在当你转换一个现存的代码库到 React 可能比较繁琐,或者和一个非 React 库集成 React 应用。在这些情况下,你可能希望使用[未控制组件](https://facebook.github.io/react/docs/uncontrolled-components.html),是一个实现输入表单的替代技术。