react笔记(四)—— 事件处理

1,281 阅读4分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第4天,点击查看活动详情

前言

大家好呀,我是L同学。在上篇文章react笔记(三)—— 组件中,我们学习了react的组件介绍、创建函数组件和类组件、有状态组件和无状态组件等相关知识点。在这篇文章中,我们将学习类组件的状态、事件处理、setState修改状态、react核心理念-状态不可变等相关知识点。

类组件的状态

react类组件中,状态state就是数据,是组件内部的私有数据,只有在组件内部可以使用。state的值是一个对象,表示一个组件中可以有多个数据。可以通过 this.state.xxx 来获取状态。

state的基本使用。

class Hello extends Component {
  state = {
    count: 0
  }

  render() {
    return (
      <div>计数器:{this.state.count}</div>
    )
  }
}

事件处理

注册事件

React注册事件与DOM的事件语法非常像。语法on+事件名={事件处理程序} 比如onClick={this.handleClick}。React事件采用驼峰命名法,比如onMouseEnter, onClick

class App extends React.Component {
  render() {
    return (
      <div>
        <button onClick={this.handleClick}>点我</button>
      </div>
    )
  }
  handleClick() {
      console.log('点击事件触发')
  }
}

事件对象

可以通过事件处理程序的参数获取到事件对象。

function handleClick(e) {
    e.preventDefault()
    console.log('事件对象', e)
}
<a onClick={this.handleClick}>点我,不会跳转页面</a>

this指向问题

在react中,事件处理函数中的this指向的是undefined。render方法中的this指向的而是当前react组件,只有事件处理程序中的this有问题。因为事件处理程序的函数式函数调用模式,在严格模式下,this指向undefined。render函数是被组件实例调用的,因此render函数中的this指向当前组件。

class App extends React.Component {
  state = {
    msg: 'hello react'
  }
  handleClick() {
    console.log(this.state.msg)
  }
  render() {
    return (
      <div>
        <button onClick={this.handleClick}>点我</button>
      </div>
    )
  }
}

this指向解决方案

解决事件处理程序中this指向问题主要有三种方式。

方式1。

class App extends React.Component {
  state = {
    msg: 'hello react'
  }
  handleClick() {
    console.log(this.state.msg)
  }
  render() {
    return (
      <div>
        <button onClick={() => {this.handleClick()}}>点我</button>
      </div>
    )
  }
}

方式二, 使用bind。

class App extends React.Component {
  state = {
    msg: 'hello react'
  }
  handleClick() {
    console.log(this.state.msg)
  }
  render() {
    return (
      <div>
        <button onClick={this.handleClick.bind(this)}>点我</button>
      </div>
    )
  }
}

方式3(最方便,使用最多)。

class App extends React.Component {
  state = {
    msg: 'hello react'
  }

  handleClick = () => {
    console.log(this.state.msg)
  }
  render() {
    return (
      <div>
        <button onClick={this.handleClick}>点我</button>
      </div>
    )
  }
}

setState修改状态

react中通过this.setState({ 要修改的部分数据 })修改状态。setState() 作用:1. 修改 state 2. 更新 UI。数据驱动视图,也就是只需要修改数据(状态)那么页面(视图)就会自动的刷新。我们关心的是如何修改数据,而不再是关心如何修改DOM。注意:尽量避免直接手动 DOM(通过 document.querySelector() 获取到到DOM对象然后再操作)。不要直接修改 state 中的值,这是无效的

class Hello extends Component {
  state = {
    count: 0
  }

  render() {
    return (
      <div>
        <h1>计数器:{this.state.count}</h1>
        <button onClick={() => {
          // 将 count 状态值修改为:10
          this.setState({
            count: 10
          })
        }}>+1</button>
      </div>
    )
  }
}

// 在 count 当前值的基础上加 10
this.setState({
  count: this.state.count + 10
})

react核心理念-状态不可变

不要直接修改当前状态值,而是创建新的状态值。

  state = {
    count: 0,
    list: [1, 2, 3],
    person: {
      name: 'jack',
      age: 18
    }
  }
  
  // 【不推荐】直接修改当前值的操作:
  this.state.count++
  ++this.state.count
  this.state.count += 1
  this.state.count = 1
  this.state.list.push(123)
  this.state.person.name = 'rose'
  
  // 【推荐】不是直接修改当前值,而是创建新值的操作:
  this.setState({
    count: this.state.count + 1,
    list: [...this.state.list],
    person: {
      ...this.state.person,
    	// 要修改的属性,会覆盖原来的属性,这样,就可以达到修改对象中属性的目的了  
      name: 'rose'
    }
  })

表单处理-受控组件

使用 React 处理表单元素,有两种方式:

  1. 受控组件【推荐】
  2. 非受控组件

HTML中表单元素是可输入的,即表单用户并维护着自己的可变状态(value)。但是在react中,可变状态通常是保存在state中的,并且要求状态只能通过setState进行修改。React中将state中的数据与表单元素的value值绑定到了一起,由state的值来控制表单元素的值

受控组件:value值受到了react控制的表单元素

使用受控组件的方式处理表单元素后,状态的值就是表单元素的值。即:想要操作表单元素的值,只需要操作对应的状态即可。

class App extends React.Component {
  state = {
    msg: 'hello react'
  }

  handleChange = (e) => {
    this.setState({
      msg: e.target.value
    })
  }

  render() {
    return (
      <div>
        <input type="text" value={this.state.msg} onChange={this.handleChange}/>
      </div>
    )
  }
}

表单处理-非受控组件-ref

非受控组件借助于ref,使用原生DOM的方式来获取表单元素的值。受控组件是通过 React 组件的状态来控制表单元素的值。非受控组件是通过手动操作 DOM 的方式来控制。此时,需要用到一个新的概念:ref。ref用来在 React 中获取 DOM 元素。

import { createRef } from 'react'

class Hello extends Component {
  txtRef = createRef()

  handleClick = () => {
    // 文本框对应的 DOM 元素
    // console.log(this.txtRef.current)

    // 文本框的值:
    console.log(this.txtRef.current.value)
  }

  render() {
    return (
      <div>
        <input ref={this.txtRef} />
        <button onClick={handleClick}>获取文本框的值</button>
      </div>
    )
  }
}