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: ''
  })
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值