表单
在React里,HTML表单元素的工作方式和其他的DOM的元素有些不用,这是因为表单元素通常会保持一些内部的state,例如这个纯html表单直接收一个名称:
<form>
<label>
名称:
<input type="text" name="name"/>
</label>
<input type="submit" value="提交" />
</form>
此表单具有默认的HTML表单行为,即在用户提交表单后浏览到新页面。
如果你在React中执行相同的代码,他依然有效,但是大多数情况下,使用JavaScript函数可以很方便的处理表单的提交,同时还可以访问用户填写的表单数据。实现这种效果的标准方式是使用"受控组件"。
受控组件
在HTML中,表单元素(如,和)之类的表单元素通常自己维护state,并根据用户输入进行更新。而在React中,可变状态通常保存在组件的state中,并且只能通过setState
来更新。
我们可以吧两者结合起来,使React的state成为唯一数据源
。渲染表单的React组件还控制着用户输入过程中表单发生的操作。被React以这种方式控制取值的表单输入元素叫做“受控组件”。
假如,如果我们想让前一个实例在提交时候打印出名称,我么可以将表单写成受控组件:
class NameForm extends React.Component {
constructor(props) {
super(props)
this.state = {
value: props.value ? props.value : ""
}
}
handleChange = (event) => {
this.setState({ value: event.target.value });
}
handleSubmit = (event) => {
alert('提交的名字: ' + this.state.value);
event.preventDefault();
}
render(){
return (
<form onSubmit = { this.handleSubmit}>
<div>{this.state.value}</div>
<label>
名字:
<input type="text" value={this.state.value} onChange = { this.handleChange } />
</label>
<input type="submit" value="提交" />
</form>
)
}
}
ReactDOM.render(<NameForm/>,document.querySelector('#root'))
由于在表单元素上设置了value
属性,因此显示的值将始终为this.state.value
,这使得React的state成为唯一数据源。由于handleChange
在每次按键时都会执行并更新React的state,因此显示的值将随着用户输入而更新。
对于受控组件来说,输入的值始终由React的state驱动。你也可以将value传递给其他UI元素,或者通过其他时间处理函数重置,但是意味着你需要编写更多的代码。
textarea 标签
在HTML中,<textarea>
元素通过其子元素定义其文本:
<textarea>
你好, 这是在 text area 里的文本
</textarea>
而在React中,使用value属性代替。这样,可以使得使用<textarea>
的表单和使用单行的input的表单非常类似:
class TextareaControl extends React.Component {
constructor(props) {
super(props)
this.state = {
value: props.value ? props.value : ""
}
}
handleSubmit = () => {
alert(this.state.value)
}
handleChange = (ev) => {
this.setState({
value: ev.target.value
})
}
render () {
return (
<form onSubmit={this.handleSubmit}>
<div>{this.state.value}</div>
<label>
名字:
<textarea type="text" value={this.state.value} onChange={this.handleChange} />
</label>
<input type="submit" value="提交" />
</form>
)
}
}
ReactDOM.render(<TextareaControl />, document.querySelector('#root'))
select标签
在HTML中,<select>
创建下拉列表标签。例如,如下HTML创建了水果相关的下拉列表:
<select>
<option value="grapefruit">葡萄柚</option>
<option value="lime">酸橙</option>
<option selected value="coconut">椰子</option>
<option value="mango">芒果</option>
</select>
请注意,由于selected属性的缘故,椰子选项默认被选中。React并不会使用
selected属性,而是在根
select`标签上使用value属性,这在受控组件中更便捷,因为你只需要在根标签中更新他。
class SelectControl extends TextareaControl {
constructor(props) {
super(props)
}
render () {
return (
<form onSubmit={this.handleSubmit}>
<label>
选择你喜欢的风味:{this.state.value}
<select value={this.state.value} onChange={this.handleChange}>
<option value="grapefruit">葡萄柚</option>
<option value="lime">酸橙</option>
<option value="coconut">椰子</option>
<option value="mango">芒果</option>
</select>
</label>
<input type="submit" value="提交" />
</form>
);
}
}
ReactDOM.render(<SelectControl />, document.querySelector('#root'))
总的来说,这使得 , 和 之类的标签都非常相似—它们都接受一个 value 属性,你可以使用它来实现受控组件
文件input标签
在HTML中,<input type="file">
允许用户从储存设备中选择一个或多个文件,将其上传到服务器,或者通过使用JavaScript的File API
进行控制。
<input type="file">
因为它的value是只读,所以它是React中的一个非受控组件。
处理多个输入
当需要处理多个input
元素时,我们可以给元素添加name
属性,并让处理函数根据event.target.name
的值选择要执行的操作。
class Reservation extends React.Component {
constructor(props) {
super(props);
this.state = {
isGoing: true,
numberOfGuests: 2
}
}
handleInputChange = (ev) => {
const target = ev.target;
const value = target.name === 'isGoing' ? target.checked : target.value;
const name = target.name;
this.setState({
[name]: value
})
}
render () {
return (
<form>
{JSON.stringify(this.state)}
<label>
参与:
<input
name="isGoing"
type="checkbox"
checked={this.state.isGoing}
onChange={this.handleInputChange} />
</label>
<br />
<label>
来宾人数:
<input
name="numberOfGuests"
type="number"
value={this.state.numberOfGuests}
onChange={this.handleInputChange} />
</label>
</form>
)
}
}
ReactDOM.render( <Reservation />,document.querySelector("#root"))
这里使用了 ES6 计算属性名称的语法更新给定输入名称对应的 state 值:
等同于ES5的
var partialState = {};
partialState[name]=value;
this.setState(partialState)
另外由于setState
自动将部分的state合并到当前state,只需要调用它更改部分的state即可。
受控输入空值
在受控组件上指定value
的prop会阻止用户更改输入。如果你执行了value,单输入仍可编辑,则可能是你意外地将value设置成了undefined或null。
ReactDOM.render( <input value="hi" onChange={()=>{}}/>,document.querySelector("#root"))
setTimeout(function() {
ReactDOM.render(<input value={null} onChange={()=>{}} />, document.querySelector("#root"));
}, 1000);
受控组件的代替品
有时使用受控组件会很麻烦,因为你需要为数据变化的每种方式编写时间处理函数,并通过一个React组件传递所有的输入state。当你将之前的代码库转化为React或将React应用程序与非React库集成的时,这可能令人厌烦。在这种情况下,你可能希望使用非受控组件。
本文地址:https://blog.csdn.net/qq_41914181/article/details/111146540