“受控“组件和”非受控“组件通常是指的表单元素。
但是有时如果通过props将数据传入某个组件,该组件受props数据控制,也可称为“受控”组件。
如果只是受state的数据影响,则称为“非受控”组件。
下面介绍的主要是表单类的组件。
1. 受控组件
通过React的state作为数据唯一来源,通过变更函数调用setState方法更新数据的表单输入元素。
它们的初始值,是this.state的初始值。
1. input的type="text/number/其他输入格式"的元素,value属性,显示和控制数据; 取值e.target.value;
2. select元素也通过value控制数据,但是它的value可以通过设置multiple,传入一个数组;取值e.target.value;
3. textarea元素通过value属性显示和控制数据;取值e.target.value;
4. type="checkbox"或者"radio", 通过checked属性,显示和控制数据;取值e.target.checked;
5. 都通过onChange事件属性的处理函数及setState,来更新表单的值;
6. 如果遇到多个受控组件一起,为了合并使用处理函数,给组件添加name属性;
7. value或者checked的值如果是undefined或者null,则相当于非受控组件;
否则,如果不使用处理函数,值无法修改。
class InputForm extends React.Component{ constructor(props) { super(props); this.state = { textValue: 'initial', checked: false, radioed: false, areaValue: '', selectValue: '' } } handleChangeInput = (e) => {//处理函数 const target = e.target; const type = target.type; const checkedTypes = ['radio', 'checkbox']; // ['radio', 'checkbox']类型的取值是e.target.value // 其余类型的取值是e.target.value let value = checkedTypes.includes(type) ? target.checked : target.value; console.log(value); const name = target.name; this.setState({ [name]: value }) } render() { return ( <form> {/*所有的受控组件设置一个name属性,用于区分是哪个组件*/} <input name="textValue" type="text" // 使用value传值 value={this.state.textValue} onChange={this.handleChangeInput} /> <input name="checked" type="checkbox" // 使用checked传值 checked={this.state.checked} onChange={this.handleChangeInput} /> <input name="radioed" type="radio" // 使用checked传值 checked={this.state.radioed} onChange={this.handleChangeInput} /> <textarea name="areaValue" // 使用value传值 value={this.state.areaValue} onChange={this.handleChangeInput} /> <select name="selectValue" // 使用value传值 value={this.state.selectValue} onChange={this.handleChangeInput} > <option value="a">A</option> <option value="b">B</option> <option value="c">C</option> <option value="d">D</option> </select> </form> ) } }
2. 非受控组件
不能通过代码来控制值,只能通过用户行为操作值。通过DOM节点来处理数据。
1. type="file'的input元素是非受控组件;input的其他类型,当不使用value时,是非受控组件;
2. type="file"也可以传入multiple属性,传多个文件;
3. 组件中使用ref属性,获取DOM节点的值;
4. input[text]/select/textarea,有defaultValue属性在初次渲染时赋予初始值;
input[checkbox][radio], 有defaultChecked属性来赋初值;
class InputForm extends React.Component{ constructor(props) { super(props); this.inputRef = React.createRef(); this.fileRef = React.createRef(); this.selectRef = React.createRef(); this.checkRef = React.createRef(); } handleSubmit = (e) => { e.preventDefault(); //阻止表单默认提交 const inputValue = this.inputRef.current.value; const selectValue = this.selectRef.current.value; const files = this.fileRef.current.files[0]; //单个文件 const checkValue = this.checkRef.current.checked; console.log(inputValue,files,selectValue,checkValue) } render() { return ( <form onSubmit={this.handleSubmit}> <input type="text" // defaultValue初值 defaultValue="输入" ref={this.inputRef} /> <input type="checkbox" // defaultChecked初值 defaultChecked ref={this.checkRef} /> <input type="file" ref={this.fileRef} /> <select defaultValue="c" //初值 ref={this.selectRef} > <option value="a">A</option> <option value="b">B</option> <option value="c">C</option> <option value="d">D</option> </select> <input type='submit'/> </form> ) } }
3. 使用场景
只能使用受控组件:
1. 即时的表单字段校验(取值范围等)
2. 强制输入格式校验
3. 按条件禁用按钮等