• React 表单受控组件(双向绑定数据)、非受控组件、React组件综合案例


    一、受控组件

    相当于数据的双向绑定,理解为vue中的v-model。将input的值存入state中。

    • HTML中的表单元素是可输入的,也就是有自己的可变状态
    • 而React中可变状态通常保存在state中,并且只能通过setState() 方法来修改
    • React将state与表单元素值value绑定在一起,有state的值来控制表单元素的值
    • 受控组件:值受到react控制的表单元素

    在这里插入图片描述

    使用步骤

    • 在state中添加一个状态,作为表单元素的value值
    • 给表单元素绑定change事件,将表单元素的值设置为state的值

    示例demo

    class App extends React.Component {
        constructor(){
            super()
            this.inputChange = this.inputChange.bind(this)
            //bind使inputChange里的this 指向class类的this
        }
        state = {
            txt : ''
        }
        inputChange(e){
           this.setState({
               txt: e.target.value
           })
        }
        render(){
            console.log(this.state);
            
            return (
                <div>
                    {/* 把state的值设置给输入框的value,绑定change事件,这样用户在输入内容的时候调用相应函数,在函数里面把当前设置的值赋值给state,从而达到数据的统一 */}
                    <input type="text" value={this.state.txt} onChange={this.inputChange}/>
                </div>
            )
        }
    }
    ReactDOM.render(<App />,document.getElementById('root'))
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    在这里插入图片描述
    在这里插入图片描述

    多表单元素示例

    在这里插入图片描述
    在这里插入图片描述

    多表单元素优化

    • 问题:每个表单元素都有一个单独的事件处理函数,这样太繁琐
    • 优化:使用一个事件处理程序同时处理多个表单元素

    步骤

    • 给表单元素添加name属性(用来区分是哪一个表单),名称与state相同(用来更新数据的)
    • 根据表单内容来获取对应值
    • 在change事件处理程序中通过 [name] 来修改对应的state
    inputChange(e){
       let target = e.target;
       let value = target.type == 'checkbox' ? target.checked : target.value;
       this.setState({
           [e.target.name]: value
       })
    }
    <input type="text" value={this.state.txt} name="txt" onChange={this.inputChange}/>
    <input type="checkbox" value={this.state.isChecked} name="isChecked" onChange={this.inputChange}/>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    在这里插入图片描述

    二、非受控组件 (了解)

    • 说明:借助于ref,使用元素DOM方式获取表单元素值
    • ref的作用:获取DOM或者组件

    使用步骤

    • 调用 React.createRef() 方法创建ref对象
    • 将创建好的 ref 对象添加到文本框中
    • 通过ref对象获取到文本框的值
    class App extends React.Component {
        constructor(){
            super()
            
            //创建 ref
            this.txtRef = React.createRef()
        }
        // 获取文本框的值
        getTxt =() => {
            console.log(this.txtRef.current.value)
        }
        render(){
            return (
              <div>
                <input type ="text" ref={this.txtRef} />
                <button onClick ={this.getTxt}>获取值</button>
              </div>
            )
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    在这里插入图片描述

    三、React组件综合案例

    需求分析

    • 渲染评论列表(列表渲染)
    • 没有评论数据时渲染:暂无评论(条件渲染)
    • 获取评论信息,包括评论人和评论内容(受控组件)
    • 发表评论,更新评论列表(setState()

    在这里插入图片描述

    class App extends React.Component {
      state = {
        userName: '',
        userContent: '',
        comments: [
          { id: 1, name: 'jack', content: '沙发!!!' },
          { id: 2, name: 'rose', content: '板凳~' },
          { id: 3, name: 'tom', content: '楼主好人' }
        ]
      }
    
      // 渲染暂无评论
      renderList() {
        return this.state.comments.length > 0 ? (
          <ul> {
            this.state.comments.map(item => {
              return (
                <li key={item.id}>
                  <h3>{item.name}</h3>
                  <p>{item.content}</p>
                </li>
              )
            })
          }
          </ul>)
          : (<div className="no-comment">暂无评论,快去评论吧~</div>)
      }
    
      // 双向绑定表单
      handleChange = e => {
        this.setState({
          [e.target.name]: e.target.value
        })
      }
    
      // 绑定点击事件
      handleClick = e => {
        //拿到用户输入的内容
        let { userName, userContent } = this.state
        if (userName.trim === '' || userContent.trim() === '') {
          alert('请输入内容')
          return
        }
    
        // 利用数组拓展运算符来进行数据的拼接,把用户输入的存放在数组的第一个位置
        let newComments = [
          {
            id: this.state.comments.length + 1,
            name: userName,
            content: userContent
          }, ...this.state.comments
        ]
    
        this.setState(
          {
            comments: newComments,
            userName: '',
            userContent: ''
          }
        )
      }
    
      render() {
        return (
          <div className='box'>
            <input type="text" placeholder='请输入评论人' className='user' name="userName" value={this.state.userName} onChange={this.handleChange}></input>
            <textarea className='content' name="userContent" value={this.state.userContent} onChange={this.handleChange}></textarea>
            <button onClick={this.handleClick}>发表评论</button>
            <div style={{ "height": "200px", "width": "100%", 'overflow': 'scroll' }}>
              {this.renderList()}
            </div>
    
          </div>
    
        )
      }
    
    }
    
    createRoot(document.getElementById('root')).render(<App></App>)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80

    index.css

    .box {
    
      display:  flex;
    
      flex-direction: column;
    
      justify-content: space-between;
    
      box-sizing: border-box;
      
      padding: 10px;
    
      width: 300px;
      height: 500px;
    
      border: 1px solid grey;
    
      margin: 0 auto;
    
    }
    
    .user{
      width: 100%;
    }
    
    .content{
    
      width: 100%;
      height: 40%;
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    四、表单处理

    获取用户所填写的内容我们必须要监听表单onChange事件,在表单项发生变化时获取其中的内容,在响应函数中通过事件对象的target.value来获取用户填写的内容

    const nameChangeHandler= e => {
         //e.target.value 表示当前用户输入的值
    };
    
    • 1
    • 2
    • 3

    然后我们再将该函数设置为input元素的onChange事件的响应函数:

    <div>
        用户名 <input type="text" onChange={nameChangeHandler}/>
    </div>
    
    • 1
    • 2
    • 3

    这样一来当用户输入内容时,nameChangeHandler就会被触发,从而通过e.target.value来获取用户输入的值。通常我们还会为表单项创建一个state用来存储值:

    const [inputName, setInputName] = useState(''); 
    const nameChangeHandler = e => {
        //e.target.value 表示当前用户输入的值
        setInputName(e.target.value);
     };
    
    • 1
    • 2
    • 3
    • 4
    • 5

    上例中用户名存储到了变量inputName中,inputName也会设置为对应表单项的value属性值,这样一来当inputName发生变化时,表单项中的内容也会随之改变:

    <div>
        用户名 <input type="text" onChange={nameChangeHandler} value={inputName}/>
    </div>
    
    • 1
    • 2
    • 3

    当用户输入内容后会触发onChange事件从而调用nameChangeHandler函数,在函数内部调用了setInputName设置了用户输入的用户名。
    在表单中输入内容会影响到state的值,同时当我们修改state的值时,由于表单项的value属性值指向了state,表单也会随state值一起改变。这种绑定方式我们称为双向绑定,即表单会改变state,state也可以改变表单,在开发中使用双向绑定的表单项是最佳实践。

    那么表单的提交要如何处理呢?表单提交同样需要通过事件来处理,提交表单的事件通过form标签的onSubmit事件来绑定,处理表单的方式因情况而已,但是一定要注意,必须要取消默认行为,否则会触发表单的默认提交行为:

    const formSubmitHandler = e => {
        e.preventDefault();
        /*
         * username : inputName
         * password : pwdInput
         * email : inputEmail     
         * */
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    为表单绑定事件:

    <form onSubmit={formSubmitHandler}>
    ......
    </form>
    
    • 1
    • 2
    • 3

    如此我们便有了一个简单的表单案例,完整代码如下:
    在这里插入图片描述
    在这里插入图片描述
    在这个案例中,表单的所有功能包括输入、显示、提交全部都由React所处理。这种表单项在React中被称为受控组件,即表单项受React控制。当然也存在有不受控组件,但那种组件使用机会少且需要通过原生DOM去操作表单,并不建议使用,所以这里便不再赘述了。

  • 相关阅读:
    第三章 shell条件测试
    wllllllll
    不念过往,不畏将来:2022年6月我辞职了...
    计算机毕业设计(附源码)python志愿者活动管理平台
    两种方式实现websocket获取数据库查询进度
    【面试题】JS 常见的 6 种继承方式(常见)
    算法基础学习|排序
    FaceNet-pytorch(fixing data imbalance-CASIA)
    如何使用JavaMailSender给曾经心爱的她发送一封特别的邮件
    漏洞复现-docker容器逃逸与研究
  • 原文地址:https://blog.csdn.net/qq_43472877/article/details/127726959