受控组件和非受控组件(一)

233 阅读2分钟

受控组件

React里面,HTML的表单元素工作方式和其他DOM不太一样。表单元素通常会维护内部的状态,这些状态会根据用户的输入而更新。而React中,可变状态通常保存在state中,并且只能通过setState更新。

所以React就把这两种方式结合起来,让state成为React的“唯一数据源”。并且React还控制着用户的输入过程中表单发生的操作。被 React 以这种方式控制取值的表单输入元素就叫做“受控组件”。

所谓的受控组件和非受控组件,是针对表单元素而言的。

受控组件有以下几个特点:

  • 表单元素依赖于状态,它的值始终由React的state来驱动。
  • 表单元素的修改,会实时映射到state,跟双向绑定类似。
  • 必须继承React.Component
  • 受控组件必须在表单上使用onChange来绑定事件

常见的受控组件

  1. input
class InputForm extends React.Component {
	constructor(props){
		this.state = {
			value: ''
		}
	}
	this.handleChange = handleChange.bind(this);
	handleChange(e){
		this.setState({value: e.target.value})
	}
	render(){
		return (
			<form>
				<input
					value={this.state.value}
					onChange={this.handleChange}
				/>
			</form>
		)
	}
}

但如果input标签的type取值为“file”,它的value是只读的,所以它是非受控组件。

  1. textarea
class TextAreaForm extends React.Component {
	constructor(){
		this.state = {
			value: "默认文本"
		}
	}
	render(){
		return (
			<textarea 
        value={this.state.value} 
        onChange={(e) => {this.setState({value: e.target.value})}}
			/>
		)
	}
}
  1. select

    React不会使用selected属性,而是在selected标签里用value表示选中项。

    对于多选框。可以在value里传入一个数组。

class SelectForm extends React.Component {
	cosntructor(){
		this.state = {
			value: "item1"
			// value: ["item1", "item2"]
		}
	}
	render(){
		return (
			<select
      	{/* mutiply={true} */}
				value={this.state.value}
				onChange={(e) => {this.setState({e.target.value})}}
			>
          <option value="item1">item1</option>
          <option value="item2">item2</option>
          <option value="item3">item3</option>
			</select>
		)
	}
}

注意:

  • 我们必须给受控组件添加onChange事件监听函数,否则浏览器会报错:受控组件

    解决办法:设置readOnly属性或者添加onChange函数

  • 当我们给input的value属性指定一个和state相关的值,或者没有在onChange函数中写setState逻辑,会阻止用户的输入,但指定null或undefined除外:

// 用户无法输入
<input value="hi"/>
<input value={this.state.value} onChange={()=>{}}
// 用户可以输入
<input value={null} />
<input value={undefined} />

有时候,使用受控组件是件很麻烦的事情,需要为数据变化的每一种方式都编写处理函数,并通过一个React组件传递所有的state。如果将非React代码转成React代码或者做React代码和非React代码集成时,会非常繁琐。这些情况下,可以引用非受控组件——表单的另一种实现方式。

参考资料:

React官方文档