受控组件

  1. 组件的使用者,有能力完全控制该组件的行为和内容。
  2. 通常情况下,受控组件往往没有自身的状态,其内容完全受到组件的使用者的属性的控制

    非受控组件

    组件的使用者,没有能力控制该组件的行为和内容,组件的行为和内容完全自行控制

    表单组件

  3. 默认情况下是 非受控组件

  4. 可以成为受控组件
  5. 一旦其设置了value属性,则其变为受控组件

    1. <input type="text" value="wjw" />
    2. //它成为了受控组件,但是没有提供 onChange事件处理函数, 故它的值无法更改,readOnly且恒为wjw
    3. //defaultValue就是非受控组件

    一般都是给关键属性设为state,然后绑定onChange,使其受控
    input type类型不同,需要设置不同的属性变为受控组件:

  6. text: value

  7. checkbox:checked

    image.png
    单选/多选select与option也需要用value

统一设置各种表单元素的onChange事件处理函数:

  1. //当时这个代码是在类组件里写的
  2. handleChange = e => {
  3. let val = e.target.value;//读取表单元素的值
  4. let name = e.target.name;//读取表单元素的name属性,作为要设置的state的属性名
  5. if(e.target.type === 'checkbox'){
  6. console.log('input的多选框');
  7. //对val进行特殊处理
  8. if(e.target.checked){
  9. val = [...this.state.chooseLoves, val];
  10. }else{
  11. val = this.state.chooseLoves.filter(it => it!==val);
  12. }
  13. }
  14. //类组件中可以直接this.setState({[name]: val});因为它在这里采取的是混合
  15. this.setState((state)=>{
  16. return {
  17. ...this.state,
  18. [name]: val,
  19. };
  20. })
  21. }

image.png
image.png
image.png
image.png

image.png
image.png

封装表单组件

下述做的是input的checkbox多选框,其他单选框、下拉列表啥的,根据这个修改下数据类型,dom结构等就行

  1. //CheckBoxGroup.js
  2. import React, { Component } from 'react'
  3. /**
  4. * 一组多选框
  5. * 需要的属性:
  6. * 1. data: 一个数组,每一项是一个对象,对应一个多选框
  7. * 1. 对象具有value和text属性
  8. * 2. value表示多选框的值
  9. * 3. text表示多选框的文本
  10. * 2. name:每一个多选框的name属性值
  11. * 3. chooseData:数组,表示当前选中的value值
  12. * 4. onChange:当选中项发生改变时的事件
  13. *
  14. * 例如:
  15. * data= [
  16. * {value: "movie", name: "电影"}
  17. * ];
  18. */
  19. export default class CheckBoxGroup extends Component {
  20. handleChange = e => {
  21. let newArr = null;
  22. //返回新的数组
  23. if(e.target.checked){
  24. newArr = [...this.props.chooseData, e.target.value];//加入
  25. }else{
  26. newArr = this.props.chooseData.filter(it=>it!==e.target.value);//筛选
  27. }
  28. //再执行父组件的onChange事件,我管你要啥参数,都先给你
  29. this.props.onChange && this.props.onChange(newArr, this.props.name, e);
  30. }
  31. //得到一组多选框
  32. getCheckBoxes(){
  33. return this.props.data.map((it,index)=>(
  34. <p>
  35. <label key={it.value}>
  36. <input
  37. type="checkbox"
  38. name={this.props.name}
  39. value={it.value}
  40. checked={this.props.chooseData.includes(it.value)}
  41. onChange={this.handleChange}
  42. />
  43. {it.text}
  44. </label>
  45. </p>
  46. ));
  47. }
  48. render() {
  49. const bs = this.getCheckBoxes();
  50. return (
  51. <div>
  52. {bs}
  53. </div>
  54. )
  55. }
  56. }
  57. //Test.js
  58. import React, { Component } from 'react';
  59. import CheckBoxGroup from "./CheckBoxGroup";
  60. import {getAllStudents} from "../../services/students"
  61. export default class Test extends Component {
  62. state = {
  63. data:[
  64. { value: 'football', text: '足球'},
  65. { value: 'basketball', text: '篮球'},
  66. { value: 'movie', text: '电影'},
  67. ],
  68. name: "loves",
  69. chooseData: ["football",]
  70. }
  71. async componentDidMount(){
  72. const students = await getAllStudents();
  73. this.setState({
  74. data: students.map(it=>({value: it.id.toString(), text: it.name}))
  75. });
  76. }
  77. render() {
  78. return (
  79. <div>
  80. <CheckBoxGroup
  81. {...this.state}
  82. onChange={(newArr)=>{
  83. this.setState({
  84. chooseData: newArr,
  85. });
  86. }}
  87. />
  88. </div>
  89. )
  90. }
  91. }