1、受控组件
- 在 React 中,可变状态(mutable state)通常保存在组件的 state 属性中,并且只能通过使用
setState()
来更新。 - state:唯一数据源
- 渲染表单的 React 组件还控制着用户输入过程中表单发生的操作。被 React 以这种方式控制取值的表单输入元素就叫做“受控组件”。
- 示例:
123456789101112131415161718192021222324252627282930313233343536373839class 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) {console.log('提交的名字:' + this.state.value)event.preventDefault()}render () {return (<form onSubmit={ this.handleSubmit }><label>名字:<inputtype="text"value={ this.state.value }onChange={ this.handleChange } /></label><input type="submit" value="提交" /></form>)}}ReactDOM.render(<NameForm />,document.getElementById('root'))
2、Textarea标签
- 在 HTML 中,
<textarea>
元素通过其子元素定义其文本
123<textarea>你好, 这是在 text area 里的文本</textarea> - 在 React 中,
<textarea>
使用value
属性代替 - 示例:
123456789101112131415161718192021222324252627282930313233343536373839class EssayForm extends React.Component {constructor (props) {super(props)this.state = {value: 'Hello Textarea!'}this.handleChange = this.handleChange.bind(this)this.handleSubmit = this.handleSubmit.bind(this)}handleChange (event) {this.setState({ value: event.target.value })}handleSubmit (event) {console.log('提交的文章:' + this.state.value)event.preventDefault()}render () {return (<form onSubmit={ this.handleSubmit }><label>文章:<textareavalue={ this.state.value }onChange={ this.handleChange } /></label><input type="submit" value="提交" /></form>)}}ReactDOM.render(<EssayForm />,document.getElementById('root2'))
3、Select标签
- 在 HTML 中,
<select>
创建下拉列表标签
123456<select><option value="grapefruit">葡萄柚</option><option value="lime">酸橙</option><option selected value="coconut">椰子</option><option value="mango">芒果</option></select> - React 在根
select
标签上使用value
属性 - 单选示例:
123456789101112131415161718192021222324252627282930313233343536373839404142class 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) {console.log('你喜欢的风味:' + this.state.value)event.preventDefault()}render () {return (<form onSubmit={ this.handleSubmit }><label>选择你喜欢的风味:<selectvalue={ 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(<FlavorForm />,document.getElementById('root3'))
- 多选示例:
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152class MultipleForm extends React.Component {constructor (props) {super(props)this.state = { value: ['A'] }this.handleChange = this.handleChange.bind(this)this.handleSubmit = this.handleSubmit.bind(this)}handleChange (event) {const option = event.target.valuelet value = this.state.valueconst index = value.indexOf(option)if (index > -1) {value.splice(index, 1)} else {value.push(option)}console.log(option, value, index)this.setState({ value })}handleSubmit (event) {console.log('你的多选:' + this.state.value)event.preventDefault()}render () {return (<form onSubmit={ this.handleSubmit }><label>多选:<selectmultiple={ true }value={ this.state.value }onClick={ this.handleChange } ><option value="A">A</option><option value="B">B</option><option value="C">C</option><option value="D">D</option></select></label><input type="submit" value="提交" /></form>)}}ReactDOM.render(<MultipleForm />,document.getElementById('root4'))
4、文件 input 标签
- 因为它的 value 只读,所以它是 React 中的一个非受控组件
1<input type="file" />
5、处理多个输入
- 当需要处理多个
input
元素时,我们可以给每个元素添加name
属性,并让处理函数根据event.target.name
的值选择要执行的操作。 - 示例:
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657class Reservation extends React.Component {constructor (props) {super(props)this.state = {isGoing: true,numberOfGuests: 2}this.handleInputChange = this.handleInputChange.bind(this)this.handleSubmit = this.handleSubmit.bind(this)}handleInputChange (event) {const target = event.targetconst value = target.name === 'isGoing' ? target.checked : target.valueconst name = target.namethis.setState({[name]: value})}handleSubmit (event) {console.log(this.state)event.preventDefault()}render () {return (<form onSubmit={ this.handleSubmit }><label>参与:<inputname="isGoing"type="checkbox"checked={ this.state.isGoing }onChange={ this.handleInputChange } /></label><br /><label>来宾人数:<inputname="numberOfGuests"type="number"value={ this.state.numberOfGuests }onChange={ this.handleInputChange } /></label><input type="submit" value="提交" /></form>)}}ReactDOM.render(<Reservation />,document.getElementById('root5'))
- 计算属性名称的语法更新给定输入名称对应的 state 值
12345678this.setState({[name]: value})// 等同ES5var partialState = {}partialState[name] = valuethis.setState(partialState)
6、受控输入空值
- 在受控组件上指定 value 的 prop 会阻止用户更改输入。如果你指定了
value
,但输入仍可编辑,则可能是你意外地将value
设置为undefined
或null
。 - 示例:
1234567let mountNode = document.getElementById('root6')ReactDOM.render(<input value="hi" />, mountNode)setTimeout(function() {ReactDOM.render(<input value={null} />, mountNode)}, 1000)
7、受控组件的替代品
- 使用非受控组件, 这是实现输入表单的另一种方式。
8、成熟的解决方案
- 包含验证、追踪访问字段以及处理表单提交的完整解决方案,使用 Formik 是不错的选择