1 受控组件
-
react 中,可变状态通常保存在组件的 state 属性中,并且只能通过
setState()
来更新。 -
渲染表单的 react 组件还控制着用户输入过程中表单发生的操作。
-
对于受控组件来说,输入的值始终由
React
的state
驱动。
1.1 input 标签
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('提交的名字:' + this.state.value)
event.preventDefault()
}
render() {
return (
<form onSubmit={ this.handleSubmit }>
<label>
名字:
<input type="text" value={ this.state.value } onChange={ this.handleChange } />
</label>
<input type="submit" value="提交" />
</form>
)
}
}
1.2 textearea 标签
class EssayForm 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('提交的内容:' + this.state.value)
event.preventDefault()
}
render() {
return (
<form onSubmit={ this.handleSubmit }>
<label>
名字:
<textarea value={ this.state.value } onChange={ this.handleChange } />
</label>
<input type="submit" value="提交" />
</form>
)
}
}
this.state.value
初始化于构造函数中,因此文本区域默认有初值
1.3 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('你喜欢的风味:' + this.state.value)
event.preventDefault()
}
render() {
return (
<form onSubmit={ this.handleSubmit }>
<label>
选择你喜欢的风味:
<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>
)
}
}
注意
- 使用
multiple={ true }
支持 select 标签多选
1.4 处理多个输入
- 当需要处理多个 input 元素时,我们可以给每个元素添加 name 属性,并让处理函数根据
event.target.name
的值选择要执行的操作
class Reservation extends React.Component {
constructor(props) {
super(props)
this.state = {
isGoing: true,
numberOfGuests: 2
}
this.handleInputChange = this.handleInputChange.bind(this)
}
handleInputChange(event) {
const { name, checked, value } = event.target
this.setState({
[name]: name=='isGoing' ? checked : value
})
}
render() {
return (
<form onSubmit={ this.handleSubmit }>
<label>
参与:
<input name="isGoing" type="checkbox" checked={ this.state.isGoing } onChange={ this.handleInputChange } />
</label>
<label>
来宾人数:
<input name="numberOfGuests" type="number" checked={ this.state.numberOfGuests } onChange={ this.handleInputChange } />
</label>
<input type="submit" value="提交">
</form>
)
}
}
1.5 受控组件输入空值
- 在受控组件上指定 value 的
prop
会阻止用户更改输入。如果你指定了 value,但输入仍可编辑,则可能是你意外地将 value 设置为undefined
或null
。
指定了 value:输入最初被锁定,但在短时间延迟后变为可编辑
2 非受控组件
大多数情况下,推荐使用 受控组件 来处理表单数据
-
在受控组件中,表单数据交由
react
组件来处理 -
在非受控组件中,表单数据交由
dom
节点来处理 -
非受控组件不是为每个状态更新都编写数据处理函数,使用
ref
来从 dom 节点中获取表单数据
class NameForm ectends React.Component {
constructor(props) {
super(props)
this.handleSubmit = this.handleSubmit.bind(this)
this.input = React.createRef()
}
handleSubmit(e) {
alert('----', this.input.current.value)
e.preventDefault()
}
render() {
return (
<form>
<label> Name:
<input type="text" ref={ this.input } />
</label>
<input type="submit" value="Submit" />
</form>
)
}
}
2.1 默认值
- 指定一个
defaultValue
属性
render() {
return (
<form>
<label>Name:
<input defaultValue="Bob" type="text" ref={ this.input } />
<label>
<input type="submit" value="Submit" />
</form>
)
}
2.2 文件输入
- react 中,
<input type="file" />
始终是一个非受控组件,因为它的值只能由用户设置不能通过代码控制
class FileInput extends React.Component {
constructor(props) {
super(props);
this.handleSubmit = this.handleSubmit.bind(this);
this.fileInput = React.createRef();
}
handleSubmit(event) {
event.preventDefault();
alert(
`Selected file - ${ this.fileInput.current.files[0].name }`
);
}
render() {
return (
<form onSubmit={ this.handleSubmit }>
<label>
Upload file:
<input type="file" ref={ this.fileInput } />
</label>
<br />
<button type="submit">Submit</button>
</form>
);
}
}
ReactDOM.render(
<FileInput />,
document.getElementById('root')
);