表格是少数几个默认为交互式的HTML元素之一。
它们被设计为允许用户与页面互动。
表格的常见用途?
- 搜索
- 联系表格
- 购物车结账
- 登录和注册
- 以及更多!
使用React,我们可以使我们的表单更具互动性,而不是静态的。
在React中,有两种处理表单的主要方式,它们在一个基本层面上是不同的:如何管理数据。
- 如果数据是由DOM处理的,我们称之为不受控制的组件
- 如果数据是由组件处理的,我们称之为受控组件。
正如你可以想象的那样,受控组件是你在大多数时候都会用到的。组件的状态是唯一的真理来源,而不是DOM。但有时你会被迫使用非控制组件,例如在使用一些表单字段时,这些字段由于其行为本身是不受控制的,如<input type="file"> 字段。
当由组件管理的表单字段中的元素状态发生变化时,我们使用onChange 属性来跟踪它。
class Form extends React.Component {
constructor(props) {
super(props)
this.state = { username: '' }
}
handleChange(event) {}
render() {
return (
<form>
Username:
<input
type="text"
value={this.state.username}
onChange={this.handleChange}
/>
</form>
)
}
}
对于类组件,为了设置新的状态,我们必须将this 绑定到handleChange 方法上,否则this 就无法从该方法中访问。
class Form extends React.Component {
constructor(props) {
super(props)
this.state = { username: '' }
this.handleChange = this.handleChange.bind(this)
}
handleChange(event) {
this.setState({ username: event.target.value })
}
render() {
return (
<form>
<input
type="text"
value={this.state.username}
onChange={this.handleChange}
/>
</form>
)
}
}
同样,当表单被提交时,我们使用表单上的onSubmit 属性来调用handleSubmit 方法。
class Form extends React.Component {
constructor(props) {
super(props)
this.state = { username: '' }
this.handleChange = this.handleChange.bind(this)
this.handleSubmit = this.handleSubmit.bind(this)
}
handleChange(event) {
this.setState({ username: event.target.value })
}
handleSubmit(event) {
alert(this.state.username)
event.preventDefault()
}
render() {
return (
<form onSubmit={this.handleSubmit}>
<input
type="text"
value={this.state.username}
onChange={this.handleChange}
/>
<input type="submit" value="Submit" />
</form>
)
}
}
使用钩子,这一切就变得简单多了。
const Form = props => {
const [username, setUsername] = useState()
const handleChangeUsername = e => {
setUsername(e.target.value)
}
const handleSubmit = event => {
alert(username)
event.preventDefault()
}
render() {
return (
<form onSubmit={handleSubmit}>
Username:
<input
type="text"
value={username}
onChange={handleChangeUsername}
/>
</form>
)
}
}
表单中的验证可以在handleChange 方法中处理:你可以访问状态的旧值和新值。你可以检查新的值,如果无效就拒绝更新的值(并以某种方式传达给用户)。
HTML表单是不一致的。它们有很长的历史,这一点很明显。然而,React使我们的事情更加一致,你可以使用它的value 属性获得(和更新)字段。
这里有一个textarea ,比如说。
<textarea value={this.state.address} onChange={this.handleChange} />
select 标签也是如此。
<select value="{this.state.age}" onChange="{this.handleChange}">
<option value="teen">Less than 18</option>
<option value="adult">18+</option>
</select>
之前我们提到了<input type="file"> 字段。这工作方式有点不同。
在这种情况下,你需要通过将ref 属性分配给构造函数中定义的属性(React.createRef() )来获得对该字段的引用,并使用该属性在提交处理程序中获得它的值。
class FileInput extends React.Component {
constructor(props) {
super(props)
this.curriculum = React.createRef()
this.handleSubmit = this.handleSubmit.bind(this)
}
handleSubmit(event) {
alert(this.curriculum.current.files[0].name)
event.preventDefault()
}
render() {
return (
<form onSubmit={this.handleSubmit}>
<input type="file" ref={this.curriculum} />
<input type="submit" value="Submit" />
</form>
)
}
}
这是不受控制的组件方式。状态被存储在DOM中,而不是在组件状态中(注意我们用this.curriculum 来访问上传的文件,而没有触及state 。
我知道你在想什么--除了这些基本的东西,一定有一个库可以简化所有这些表单处理的东西,并自动进行验证、错误处理等,对吗?有一个很好的,Formik。