当前位置:   article > 正文

【React】4.事件处理与类组件状态state_state=(state+1)%5

state=(state+1)%5

1. 事件处理

所谓事件, 就是点击事件、双击事件等等;

1.1 事件绑定

React 事件綁定语法与 DOM 事件语法相似
语法: on+事件名称={事件处理程序},比如:onClick={()=>{}}
注意: React 事件采用驼蜂命名法,比如:onMouseEnter、onFocus

在类组件中绑定事件:

import React from 'react'


/**
 * 定义一个类组件
 */
 class Fun3 extends React.Component {
    类中定义一个函数处理器
     clickHandler() {
        console.log("hello")
    }

    render() {
      return (
          //绑定单击事件,必须使用this
        <button onClick={this.clickHandler}>click me</button>
      )
    }
  }

  //导出组件,以供使用
  export default Fun3
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

在函数中绑定事件:

import { render } from '@testing-library/react'
import React from 'react'
import ReactDOM from 'react-dom/client'

//导入组件
import Fun3 from './common/Fun3'

const root = ReactDOM.createRoot(document.getElementById("root"))


function Fun4(){

  //事件处理函数
  function clickMe(){
    console.log("hello 4")
  }

  return (
    //绑定事件,无需this
    <button onClick={clickMe}>click me 4 </button>
  )
}



//使用组件,用标签符号来调用组件
root.render(<Fun4 />)

  • 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

1.2.事件对象

  • 可以通过事件处理程序的参数获取到事件对象
  • React 中的事件对象叫做:合成事件(对象)
  • 合成事件:兼容所有浏览器,无需担心跨浏览器兼容性问题

示例:
使用事件对象e,实现点击a标签时阻止跳转

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

const root = ReactDOM.createRoot(document.getElementById("root"))


function Fun4(){

  //事件处理函数
  function clickMe(e){
    console.log("hello 4")
    //阻止浏览器的默认行为,这样只会打印,不会跳转了
    e.preventDefault();
  }

  return (
    //绑定事件
    <a href='http://www.baidu.com' onClick={clickMe}> baidu </a>
  )
}



//使用组件,用标签符号来调用组件
root.render(<Fun4 />)

  • 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

2. 组件状态

2.1基本使用

函数组件没有状态,类组件才有状态

状态关键字为state,是一个对象,里面可以是任意数据

初始化状态:

state ={
	count:0,name:"tom"
}
  • 1
  • 2
  • 3

使用状态:

this.state.count
  • 1

设置状态:
只能用setState()更新状态,this.state.count=2是无效的。
只会更改指定key的值,不会影响state中的其他数据。

this.setState({count:1})
  • 1

数据驱动视图,当state变化后,会重新渲染页面。

示例:
用状态保存计数,每次点击+1

Fun3.js

import React from 'react'


/**
 * 定义一个类组件
 */
class Fun3 extends React.Component {
  //初始化state
  state = {
    count: 0
  }


  //必须使用箭头函数才能操作state,否则报错
  clickHandler = (e) => {
    this.setState({ count: this.state.count + 1 })
    console.log(this.state.count)
  }

  render() {
    return (
      //绑定单击事件,必须使用this
      <button onClick={this.clickHandler}>click me {this.state.count}</button>
    )
  }
}

//导出组件,以供使用
export default Fun3
  • 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

index.js

import React from 'react'
import ReactDOM from 'react-dom/client'
import Fun3 from './common/Fun3'


const root = ReactDOM.createRoot(document.getElementById("root"))
//使用组件,用标签符号来调用组件
root.render(<Fun3 />)

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

效果:
在这里插入图片描述

2.2 state的异步特性

  1. state 更新是异步的,setState后立刻用this.state.xxx得到的还是set前的值。
  2. 同一个方法中,后面的setState会覆盖前面的setState的值。
  3. 同一个方法中,只会触发一次render
    示例:
import React from 'react'
import ReactDOM from 'react-dom/client'
//定义一个类组件
class CountComponent extends React.Component {
  state = {
    count: 1
  }

  clickHander = () => {
    //第一次设置count
    this.setState({
      count: this.state.count + 1
    })
    console.log("count=", this.state.count)
    //第二次设置count
    this.setState({
      count: this.state.count + 10
    })
    console.log("count=", this.state.count)
  }


  render() {
    console.log("render")
    return (
      <div>
        <div>计数:{this.state.count}</div>
        <button onClick={this.clickHander}>+1</button>
      </div>
    )
  }
}
//调用高阶组件方式2

const root = ReactDOM.createRoot(document.getElementById("root"))

root.render(
  //渲染
  <CountComponent />
)
  • 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

效果:
在这里插入图片描述

2.3state推荐写法

使用函数,将state作为函数的入参,这样入参就是最新的state了

import React from 'react'
import ReactDOM from 'react-dom/client'
//定义一个类组件
class CountComponent extends React.Component {
  state = {
    count: 1
  }

  clickHander = () => {
    console.log("第1次获取connt=", this.state.count)
    this.setState((state, props) => {
      console.log("第1函数connt=", state.count)
      return {
        count: state.count + 1
      }
    })
    console.log("第2次获取connt=", this.state.count)
    this.setState((state, props) => {
      console.log("第2函数connt=", state.count)
      return {
        count: state.count + 1
      }
    })
    console.log("第3次获取connt=", this.state.count)
  }

  render() {
    console.log("render")
    return (
      <div>
        <div>计数:{this.state.count}</div>
        <button onClick={this.clickHander}>+1</button>
      </div>
    )
  }
}
//调用高阶组件方式2
const root = ReactDOM.createRoot(document.getElementById("root"))

root.render(
  //渲染
  <CountComponent />
)
  • 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

效果:
在这里插入图片描述
根据效果得出结论:

  1. setState方法是异步执行的,且是在当前方法执行完毕后执行。
  2. setState时使用state作为入参,可以直接得到最新的值。
  3. render只会一次

2.4 setState的第二个参数:回调函数

语法:

this.setState(updater[,callback])
  • 1

当设置了state后,需要执行其他逻辑,或者需要使用最新state,可以在第二个参数位置传入一个函数作为回调函数。
回调函数执行时机:setSate和render渲染后执行。
示例:

import React from 'react'
import ReactDOM from 'react-dom/client'
//定义一个类组件
class CountComponent extends React.Component {
  state = {
    count: 1
  }

  clickHander = () => {
    console.log("第1次获取connt=", this.state.count)
    this.setState((state, props) => {
      console.log("第1函数connt=", state.count)
      return {
        count: state.count + 1
      }
    },()=>{
      //第二个参数,传入一个函数,作为回调函数
      console.log("函数1回调的count=",this.state.count)
    })
    console.log("第2次获取connt=", this.state.count)

    
    this.setState((state, props) => {
      console.log("第2函数connt=", state.count)
      return {
        count: state.count + 1
      }
    },()=>{
      //第二个参数,传入一个函数,作为回调函数
      console.log("函数2回调的count=",this.state.count)
    })
    console.log("第3次获取connt=", this.state.count)
  }

  render() {
    console.log("render")
    return (
      <div>
        <div>计数:{this.state.count}</div>
        <button onClick={this.clickHander}>+1</button>
      </div>
    )
  }
}
//调用高阶组件方式2

const root = ReactDOM.createRoot(document.getElementById("root"))

root.render(
  //渲染
  <CountComponent />
)
  • 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

效果:
在这里插入图片描述
可见,回调函数在render后执行,执行顺序按书写顺序,都能拿到render后最新的state

3. 事件绑定this指向

当我们直接在函数里面使用this时,可能发生
报错:Cannot read properties of undefined (reading ‘state’)

3.1 使用箭头函数绑定

下面介绍了三种箭头函数解决this的方式:

import React from 'react'


/**
 * 定义一个类组件
 */
class Fun3 extends React.Component {
  //初始化state
  state = {
    count: 0
  }


  //解决方式1(推荐)
  clickHandler = (e) => {
    this.setState({ count: this.state.count + 1 })
    console.log(this.state.count)
  }
  //解决方式2
  clickHandler2() {
    this.setState({ count: this.state.count + 1 })
    console.log(this.state.count)
  }

  render() {
    return (
      //调用方式1
      //<button onClick={this.clickHandler}>click me {this.state.count}</button>
      //调用方式2
      //<button onClick={() => this.clickHandler2()}>click me {this.state.count}</button>
      //解决方式3
      <button onClick={() => this.setState({ count: this.state.count + 1 })}>click me {this.state.count}</button>
    )
  }
}

//导出组件,以供使用
export default Fun3
  • 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

3.2 在构造器中使用bind方法绑定

import React from 'react'


/**
 * 定义一个类组件
 */
class Fun3 extends React.Component {

  constructor(){
    super()
    //给函数绑定this
    this.clickHandler=this.clickHandler.bind(this)
  }

  //初始化state
  state = {
    count: 0
  }


  //解决方式2
  clickHandler() {
    this.setState({ count: this.state.count + 1 })
    console.log(this.state.count)
  }

  render() {
    return (
      <button onClick={this.clickHandler}>click me {this.state.count}</button>
    )
  }
}

//导出组件,以供使用
export default Fun3
  • 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
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/IT小白/article/detail/63436
推荐阅读
相关标签
  

闽ICP备14008679号