React官方文档--Forms

时间:2021-08-18 20:34:27

Forms

表单组件,比如:<input><textarea><option>和基本的组件不同,因为表单组件是需要用户进行交互的。这些组件提供了接口,用来更容易的管理表单来响应用户的交互。
有两种形式的表单组件
1. Controlled Components
2. Uncontrolled Components

Controlled Components

一个受控表单组件提供一个value属性,一个受控表单组件不会维持其内部自己的状态,组件只根据props进行渲染。

render() {
return (
<input
type="text"
value="Hello!"
/>
)
}

如果你试图去运行这里例子,会发现输入框里的内容不会随着输入而改变。因为你声明了这个组件的value值,为了更新value作为用户输入的响应,需要添加onChange事件来保存新的值,然后传递这个值给value属性。

class Form 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) {
console.log("Text field value is : " + this.state.value);
}

render() {
return (
<div>
<input type="text" placeholder="Hello!"
value={this.state.value} onChange={this.handleChange}/>
<button onClick={this.handleSubmit}>
Submit
</button>
</div>
)
}
}

ReactDOM.render(
<Form />,
document.getElementById("root")
);

在这个例子中,我们接受用户提供的值,来更新value 的值,这种方法使得继承接口或者进行表单验证变得很方便

handleChange(event) {
this.setState({
value: event.target.value.substr(0, 14)
});
}

Checkboxes和RadioButton存在的潜在问题

在使用React来监听checkbox或者radio的事件的时候,React监听一个click的浏览器事件来声明一个onChange事件,在大部分情况下这样是没有什么问题的,除非当你调用了preventDefault()在change的事件处理函数里面,preventDefault会停止浏览器在视觉上更新输入,即使checked的值已经改变了,这个问题可以通过不调用preventDefault或者将切换checked的值放在setTimeout中执行来解决。

非受控组件

不提供value属性的表单组件称为非受控组件。下面的例子渲染了一个<input>来控制一个空的值,任何用户输入的值会立刻影响到渲染的元素。
一个非受控组件管理他自己的状态。

render() {
return <input type="text" />
}

如果你希望监听这个组件的值的更新,你需要使用onChange事件来监听,就像受控组件一样,但是不能给组件传递任何值。

class Form 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("Text field value is : " + this.state.value);
}

render() {
return (
<div>
<input
type="text"
placeholder="Hello!"
onChange={this.handleChange} />
<button onClick={this.handleSubmit}>
Submit
</button>
</div>
);
}
}

ReactDOM.render(
<Form />,
document.getElementById("root")
)

当这个例子输入value的时候,我们可以通过handleSubmit()来读取,非受控表单组件不能够请求,你需要完整的onChange事件处理来取代读取value

默认值

使用一个非空的value来初始化一个非受控组件,你可以使用一个defaultValue属性

render() {
return <input type="text" defaultValue="Hello" />
}

同样地,<input type="checkbox"><input type="radio">支持defaultChecked然后<select>支持defaultValue

交互属性

表单组件支持一系列的props会通过用户交互影响组件。
1. value,是<input><textarea>支持的组件。
2. checked,是<input>组件的checkboxradio支持的
3. selected,是<option>组件支持的。
在HTML中,<textarea>的值是通过子元素来设置的,在React中,需要使用value来替代
表单组件允许通过onChange属性的回调函数来监听修改,onChange属性通过浏览器和用户交互的响应。

进阶技术

为什么使用受控组件

使用类似<input>的表单组件是和传统的HTML不相同的。

<input type="text" name="title" value="Untitle">

上面的代码渲染初始化了一个value为Untitle。当用户更新输入的时候,这个节点的value属性也会改变,然而使用node.getAttribute('value')仍然会返回初始化的时候的值:Untitled
与HTML不同的是,React组件必须一致保持其状态,也就是自从渲染之后,value的值一直保持为Untitled

Why Textarea Value

在HTML,<textarea>的值应该是其子元素的值。

<textarea name="description">This is the description.</textarea>

在HTML中,很容易允许开发人员提供多行的值,然而,在React中,我们不能够设置多行的字符串,如果要换行的话需要使用\n,在有value和defaultValue的时候,因为这个原因,你不需要使用子元素来设置<textarea>的值。

<textarea name="description" value="This is a description.">

Why Select Value

option<select>中是用selected属性来进行判断选择的,但是在React的组件中,是使用value属性的。

<select value="B">
<option value="A">Apple</option>
<option value="B">Banana</option>
<option value="C">Cranberry</option>
</select>

使用非受控组件的话,这里需要使用defaultValue

受控输入框

class Form 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('Text field value is: ' + this.state.value);
}

render() {
return (
<div>
<input
type="text"
placeholder="edit me"
value={this.state.value}
onChange={this.handleChange}
/>
<button onClick={this.handleSubmit}>
Submit
</button>
</div>
);
}
}

ReactDOM.render(
<Form />,
document.getElementById('root')
);

受控文本区组件

class Form 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("Textarea value is: " + this.state.value);
}

render() {
return (
<div>
<textarea
name="description"
value={this.state.value}
onChange={this.handleChange}
/>
<br/>
<button onClick={this.handleSubmit}>
Submit
</button>
</div>
)
}
}

ReactDOM.render(
<Form />,
document.getElementById("root")
);

受控下拉列表

class Form 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("Select value is: " + this.state.value);
}

render() {
return (
<div>
<select value={this.state.value} onChange={this.handleChange}>
<option value="A">Apple</option>
<option value="B">Banana</option>
<option value="C">Cranberry</option>
</select>
<br/>
<button onClick={this.handleSubmit}>
Submit
</button>
</div>
)
}
}

ReactDOM.render(
<Form />,
document.getElementById("root")
);

非受控单选按钮

class Form extends React.Component {
constructor(props) {
super(props);
this.state = {
value: "B"
}
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}

handleChange(event) {
this.setState({
value: event.target.value
});
}

handleSubmit(event) {
alert("Radio button value is: " + this.state.value);
}

render() {
return (
<div>
<label>
<input type="radio" name="choice" value="A" onChange={this.handleChange}/>
Option A
</label>
<label>
<input type="radio" name="choice" value="B" onChange={this.handleChange}/>
Option B
</label>
<label>
<input type="radio" defaultChecked={true} name="choice" value="C" onChange={this.handleChange}/>
Option C
</label>
<br/>
<button onClick={this.handleSubmit}>
Submit
</button>
</div>
)
}
}

ReactDOM.render(
<Form />,
document.getElementById("root")
);

非受控复选框

class Form extends React.Component {
constructor(props) {
super(props);
this.state = {
checked: {
'A': false,
'B': true,
'C': false
}
};
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}

handleChange(event) {
const value = event.target.value;

const checked = Object.assign({}, this.state.checked);
if (!checked[value]) {
checked[value] = true;
} else {
checked[value] = false;
}
this.setState({checked});
}

handleSubmit(event) {
alert("Boxes checked: " +
(this.state.checked.A ? 'A ' : ' ') +
(this.state.checked.B ? 'B ' : ' ') +
(this.state.checked.C ? 'C ' : ' ')
);
}

render() {
return (
<div>
<label>
<input type="checkbox" value="A" onChange={this.handleChange} />
Option A
</label>
<label>
<input type="checkbox" value="B" onChange={this.handleChange} defaultChecked={true}/>
Option B
</label>
<label>
<input type="checkbox" value="C" onChange={this.handleChange} />
Option C
</label>
<button onClick={this.handleSubmit}>
Submit
</button>
</div>
)
}
}

ReactDOM.render(
<Form />,
document.getElementById("root")
);