受控组件
- 组件的使用者,有能力完全控制该组件的行为和内容。
通常情况下,受控组件往往没有自身的状态,其内容完全受到组件的使用者的属性的控制
非受控组件
组件的使用者,没有能力控制该组件的行为和内容,组件的行为和内容完全自行控制
表单组件
默认情况下是 非受控组件
- 可以成为受控组件
一旦其设置了value属性,则其变为受控组件
<input type="text" value="wjw" />
//它成为了受控组件,但是没有提供 onChange事件处理函数, 故它的值无法更改,readOnly且恒为wjw
//defaultValue就是非受控组件
一般都是给关键属性设为state,然后绑定onChange,使其受控
input type类型不同,需要设置不同的属性变为受控组件:text: value
checkbox:checked
单选/多选select与option也需要用value
统一设置各种表单元素的onChange事件处理函数:
//当时这个代码是在类组件里写的
handleChange = e => {
let val = e.target.value;//读取表单元素的值
let name = e.target.name;//读取表单元素的name属性,作为要设置的state的属性名
if(e.target.type === 'checkbox'){
console.log('input的多选框');
//对val进行特殊处理
if(e.target.checked){
val = [...this.state.chooseLoves, val];
}else{
val = this.state.chooseLoves.filter(it => it!==val);
}
}
//类组件中可以直接this.setState({[name]: val});因为它在这里采取的是混合
this.setState((state)=>{
return {
...this.state,
[name]: val,
};
})
}
封装表单组件
下述做的是input的checkbox多选框,其他单选框、下拉列表啥的,根据这个修改下数据类型,dom结构等就行
//CheckBoxGroup.js
import React, { Component } from 'react'
/**
* 一组多选框
* 需要的属性:
* 1. data: 一个数组,每一项是一个对象,对应一个多选框
* 1. 对象具有value和text属性
* 2. value表示多选框的值
* 3. text表示多选框的文本
* 2. name:每一个多选框的name属性值
* 3. chooseData:数组,表示当前选中的value值
* 4. onChange:当选中项发生改变时的事件
*
* 例如:
* data= [
* {value: "movie", name: "电影"}
* ];
*/
export default class CheckBoxGroup extends Component {
handleChange = e => {
let newArr = null;
//返回新的数组
if(e.target.checked){
newArr = [...this.props.chooseData, e.target.value];//加入
}else{
newArr = this.props.chooseData.filter(it=>it!==e.target.value);//筛选
}
//再执行父组件的onChange事件,我管你要啥参数,都先给你
this.props.onChange && this.props.onChange(newArr, this.props.name, e);
}
//得到一组多选框
getCheckBoxes(){
return this.props.data.map((it,index)=>(
<p>
<label key={it.value}>
<input
type="checkbox"
name={this.props.name}
value={it.value}
checked={this.props.chooseData.includes(it.value)}
onChange={this.handleChange}
/>
{it.text}
</label>
</p>
));
}
render() {
const bs = this.getCheckBoxes();
return (
<div>
{bs}
</div>
)
}
}
//Test.js
import React, { Component } from 'react';
import CheckBoxGroup from "./CheckBoxGroup";
import {getAllStudents} from "../../services/students"
export default class Test extends Component {
state = {
data:[
{ value: 'football', text: '足球'},
{ value: 'basketball', text: '篮球'},
{ value: 'movie', text: '电影'},
],
name: "loves",
chooseData: ["football",]
}
async componentDidMount(){
const students = await getAllStudents();
this.setState({
data: students.map(it=>({value: it.id.toString(), text: it.name}))
});
}
render() {
return (
<div>
<CheckBoxGroup
{...this.state}
onChange={(newArr)=>{
this.setState({
chooseData: newArr,
});
}}
/>
</div>
)
}
}