Forms - 表单
在React中,HTML表单元素同其他DOM元素,有点不同。因为表单元素天生具备一些内部的state状态。例如:下面的HTML表单接收一个名字:
controlled components - 控制组件
在HTML中,表单元素,例如:<input> <textarea> 以及 <select> 典型的维护自己的state状态,并且基于用户的输入而更新。在React中,多变的state状态保持在 组件的state属性中,并且只能通过 setState() 来更新。
我们可以通过 令React的state状态变为 'single source of truth-但一来源?' 来结合两种方式。之后,渲染表单的React组件,也可控制表单上随后的用户输入。被React以这种方式控制的input表单元素,被称为是:'controlled components-控制组件'。
例如,我们想实现之前的例子,当表单提交时,记录name值,我们可以将表单写作一个控制组件:
由于我们的表单元素设置了 'value' 属性,展示的value值应该是 'this.state.value'来声明React值的真实来源。由于每次敲击键盘,会调用 'handleChange' 来更新React的state,当用户输入时,也会更新展示的值。
对于一个控制组件,每次状态的改变都会引起一个相关的函数调用。这将直接修改或验证用户输入。例如:如果我们想强制输入的名字全部为大写字母,我们可以如下定义 'handleChange':
textarea 标签
在HTML中,'<textarea>' 元素如下定义,文本在它的内部:
注意:'this.state.value' 在构造器中初始化,确保文本域刚开始有内部一些文本
select 标签
在HTML中,'<select>' 创建一个下拉菜单。例如,下面的HTML代码创建一个 'flavors' 的下拉列表:
总的来说,这使得 <input type="text">,<textarea>和<select> 所有都工作的非常相似-它们都接收一个 'value' 属性,可以用来实现一个控制组件。
控制组件的供选方案
有时使用控制组件是乏味的,因为通过React组件,你需要对每一种数据改变方式写一个事件处理,并管道传递(pipe)所有的输入state状态。这是极其厌烦的,当你将一个已经存在的代码转变为React代码,或者使React应用和一个非React库融合。在这些情况下,你可能想要寻求非控制组件(uncontrolled components),实现输入表单的一种替代技术
在React中,HTML表单元素同其他DOM元素,有点不同。因为表单元素天生具备一些内部的state状态。例如:下面的HTML表单接收一个名字:
<form>
Name:
<input type="text" name="name" />
<input type="submit" value="submit" />
</form>
这个表单具有默认HTML表单的行为,当用户提交表单,跳转到新页面。在React中,如果你想要这种行为,它默认就起作用。但是大多数情况,使用js函数来处理表单的提交,以及对用户输入的表单数据的访问是很方便的。实现这个目的的标准方式是,使用一个叫做 'controlled components-控制组件' 技术
controlled components - 控制组件
在HTML中,表单元素,例如:<input> <textarea> 以及 <select> 典型的维护自己的state状态,并且基于用户的输入而更新。在React中,多变的state状态保持在 组件的state属性中,并且只能通过 setState() 来更新。
我们可以通过 令React的state状态变为 'single source of truth-但一来源?' 来结合两种方式。之后,渲染表单的React组件,也可控制表单上随后的用户输入。被React以这种方式控制的input表单元素,被称为是:'controlled components-控制组件'。
例如,我们想实现之前的例子,当表单提交时,记录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}>
Name:
<input type="text" value={this.state.value}>
<input type="submit" value="Submit">
</form>
);
}
}
由于我们的表单元素设置了 'value' 属性,展示的value值应该是 'this.state.value'来声明React值的真实来源。由于每次敲击键盘,会调用 'handleChange' 来更新React的state,当用户输入时,也会更新展示的值。
对于一个控制组件,每次状态的改变都会引起一个相关的函数调用。这将直接修改或验证用户输入。例如:如果我们想强制输入的名字全部为大写字母,我们可以如下定义 'handleChange':
handleChange(event) {
this.setState({value: event.target.value.toUpperCase()});
}
textarea 标签
在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}>
Name:
<textarea value={this.state.value} onChange={this.handleChange} />
<input type="submit" value="submit">
</form>
);
}
}
注意:'this.state.value' 在构造器中初始化,确保文本域刚开始有内部一些文本
select 标签
在HTML中,'<select>' 创建一个下拉菜单。例如,下面的HTML代码创建一个 'flavors' 的下拉列表:
<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' 属性,而使用 'value' 属性在 '<select>' 根标签。在控制组件上,这会更加方便,因为你只需要在一个地方更新它的值。例如:
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}>
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>
<input type="submit" value="Submit" />
</form>
);
}
}
总的来说,这使得 <input type="text">,<textarea>和<select> 所有都工作的非常相似-它们都接收一个 'value' 属性,可以用来实现一个控制组件。
控制组件的供选方案
有时使用控制组件是乏味的,因为通过React组件,你需要对每一种数据改变方式写一个事件处理,并管道传递(pipe)所有的输入state状态。这是极其厌烦的,当你将一个已经存在的代码转变为React代码,或者使React应用和一个非React库融合。在这些情况下,你可能想要寻求非控制组件(uncontrolled components),实现输入表单的一种替代技术