React学习第四步:受控组件相关学习

Posted 黑马程序员官方

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了React学习第四步:受控组件相关学习相关的知识,希望对你有一定的参考价值。

本文目标:

  • 能够知道受控组件是什么
  • 能够写出受控组件
  • 了解非受控组件

表单处理

一、受控组件(⭐⭐⭐)

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

1.1 使用步骤

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

示例demo

class App extends React.Component 
    constructor()
        super()
        this.inputChange = this.inputChange.bind(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 多表单元素优化

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

步骤:

  • 给表单元素添加name属性(用来区分是哪一个表单),名称与state相同(用来更新数据的)
  • 根据表单内容来获取对应值
  • 在change事件处理程序中通过 [name] 来修改对应的state

示例demo

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/>

二、非受控组件(了解)

  • 说明:借助于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>
        )
    

三、React组件综合案例(⭐⭐⭐)

需求分析:

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

搭建评论列表的模板

结构:

import React from 'react'
import ReactDOM from 'react-dom'

/* 
  评论列表案例

  comments: [
     id: 1, name: 'jack', content: '沙发!!!' ,
     id: 2, name: 'rose', content: '板凳~' ,
     id: 3, name: 'tom', content: '楼主好人' 
  ]
*/

import './index.css'

class App extends React.Component 
  render() 
    return (
      <div className="app">
        <div>
          <input className="user" type="text" placeholder="请输入评论人" />
          <br />
          <textarea
            className="content"
            cols="30"
            rows="10"
            placeholder="请输入评论内容"
          />
          <br />
          <button>发表评论</button>
        </div>

        <div className="no-comment">暂无评论,快去评论吧~</div>
        <ul>
          <li>
            <h3>评论人:jack</h3>
            <p>评论内容:沙发!!!</p>
          </li>
        </ul>
      </div>
    )
  


// 渲染组件
ReactDOM.render(<App />, document.getElementById('root'))

样式:

.app 
  width: 300px;
  padding: 10px;
  border: 1px solid #999;


.user 
  width: 100%;
  box-sizing: border-box;
  margin-bottom: 10px;


.content 
  width: 100%;
  box-sizing: border-box;
  margin-bottom: 10px;


.no-comment 
  text-align: center;
  margin-top: 30px;

渲染评论列表

在state中初始化评论列表数据

  state = 
    comments: [
       id: 1, name: 'jack', content: '沙发!!!' ,
       id: 2, name: 'rose', content: '板凳~' ,
       id: 3, name: 'tom', content: '楼主好人' 
    ]
  
  • - 使用数组的map方法遍历state中的列表数据
  • - 给每一个被遍历的li元素添加key属性
  • - 在render方法里的ul节点下嵌入表达式

  this.state.comments.map(item => 
    return (
       <li key=item.id>
          <h3>item.name</h3>
          <p>item.content</p>
       </li>
    )
  )

渲染暂无评论

  • 判断列表数据的长度是否为0
  • 如果为0,则渲染暂无评论
  • 如果不为0,那么渲染列表数据
  • 在jsx中大量写逻辑会导致很臃肿,所以我们可以把条件渲染的逻辑抽取成一个函数
/**
 * 条件渲染,这里抽取出来了,这样在结构中不会很混乱
 */
renderList()
  if (this.state.comments.length === 0) 
    return (<div className="no-comment">暂无评论,快去评论吧~</div>)
   else 
    return (
      <ul> 
        this.state.comments.map(item => 
          return (
            <li key=item.id>
              <h3>item.name</h3>
              <p>item.content</p>
            </li>
          )
        )
      
      </ul>
    )
  

  • 在render的return方法里面调用这个函数即可
render() 
  return (
    <div>
      ...
      /* 通过条件渲染来判断是否显示暂无评论 */
      this.renderList()
    </div>
  )

获取评论信息

  • - 通过受控组件来获取内容
  • - 初始化用户名和用户内容的state
userName: '',
userContent: ''

在结构中,把表单元素的value与state进行绑定,还需要绑定name属性和onChange属性

<input className="user" type="text" placeholder="请输入评论人" value=this.state.userName name="userName" onChange=this.handleForm/>
<br />
<textarea
  className="content"
  cols="30"
  rows="10"
  placeholder="请输入评论内容"
  value=this.state.userContent
  name="userContent"
  onChange=this.handleForm
/>

在`handleFrom`函数中利用`setState`来让数据保持一致

  handleForm = (e) => 
     this.setState(
       [e.target.name] : e.target.value
     )
  

发表评论

  • - 给按钮绑定事件
  • - 在事件处理程序中,通过state获取评论信息
  • - 将评论信息添加到state中,利用setState来更新页面
  • - 添加评论前需要判断用户是否输入内容
  • - 添加评论后,需要情况文本框用户输入的值
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: ''
  )

以上是关于React学习第四步:受控组件相关学习的主要内容,如果未能解决你的问题,请参考以下文章

前端学习(3231):React中的受控组件

前端学习(3230):React中的非受控组件

React -- 受控组件和非受控组件

React学习目录

[React 基础系列] 受控表单 vs 不受控表单

react讲解(组件,生命周期以及受控组件)