React(四):事件总线、setState的细节、PureComponent、ref

发布于:2025-08-12 ⋅ 阅读:(12) ⋅ 点赞:(0)

一、事件总线

这里的事件总线和vue中基本一个思路。

在React中可以通过第三方库来进行任意组件通信,安装:

npm install hy-event-store

使用:
在这里插入图片描述
1、在某个地方新建jsx文件对外暴露事件总线

// 创建事件总线
import {
   
    HYEventBus } from 'hy-event-store';
const eventBus = new HYEventBus();

export default eventBus;

2、在需要接收值的组件中,在挂在完毕的生命周期函数中绑定事件和被触发时的回调,最好写上销毁的代码:

//事件的回调
 getData(name,age) {
   
   
     console.log(name,age,this);
     this.setState({
   
   
         name: name, age: age
     })
 }
 //1.挂载完毕后绑定事件接收别的地方传过来的值
 componentDidMount() {
   
   
     eventBus.on('getData', this.getData.bind(this))
 }
 //3.销毁的时候解绑
 componentWillUnmount() {
   
   
     eventBus.off('getData', this.getData)
 }

3、另一个组件触发,并传值

sendData() {
   
   
        //2.某个组件中触发事件并传值
        eventBus.emit('getData', 'zzy', 18)
    }
    render() {
   
   
        return (
            <div>
                <h1>GrandSon组件</h1>
                <button onClick={
   
   () => this.sendData()}>点击传值给App</button>
            </div>
        )
    }

二、关于setState的原理

开发中我们并不能直接通过修改state的值来让界面发生更新:
因为我们修改了state之后,希望React根据最新的State来重新渲染界面,但是这种方式的修改React并不知道数据发生了变化;
React并没有实现类似于Vue2中的Object.defineProperty或者Vue3中的Proxy的方式来通过数据劫持监听数据的变化;
我们必须通过setState来告知React数据已经发生了变化;
源码先简单lou一眼:
在这里插入图片描述

1. setState的三种使用方式

我们基于以下组件进行操作

export class Son extends React.Component {
   
   
  constructor() {
   
   
    super();
    this.state = {
   
   
      name: 'zzy',
      age: 18,
    }
  }

  changeName() {
   
   
    this.setState(...)
  }

  render() {
   
   
    return (
      <div>
        <h1>{
   
   this.state.name}</h1>
        <button onClick={
   
   () => this.changeName()}>点击修改名字</button>
      </div>

    )
  }
}

(1)基本使用

我们之前用的最多的就是直接传入一个配置对象,然后给state中数据重新赋值。这里的原理是借助了Object.assign(state, newState)state和传入的对象进行合并,如果key重复那么就进行值的覆盖,没改的继续保留

//1.基本使用,传入配置对象,不是覆盖原来的state,而是进行对象的合并
this.setState({
   
   
  name: 'ht'  //原理:对象的合并Object.assign(state, newState)
})

(2)传入一个回调

setState的参数除了可以传配置对象外,还可以传入一个回调函数,通过return一个对象,对象中包含我们要修改的值,也可以实现数据的更新和页面的重新渲染。

这个回调可以接收两个参数:state和props,分别对应的是上一个修改状态stateprops的值们。

注意是上一个修改状态!如果在一个回调中多次执行setState更改数据,那么参数state保存的是上一个修改状态的值!如果不明白请看本节2.1.1部分

//2.传入一个回调,可以接收修改之前的state和props
this.setState((state,props) => {
   
   
  console.log(state,props);
  return {
   
   
    name: 'ht' //这里也可以进行更改
  }
})

(3)第一个参数是对象,第二个参数是回调

setState是一个异步调用。

如果在setState下面使用name,我们会发现拿到的是原来的name,这就证明了setState是一个异步调用,那么如果我们想在数据变化后再基于数据进行一些操作怎么办?这时候可以传入第二个参数:一个回调函数,该回调函数执行的时机就是数据更新完且render调用完毕后

//3.setState是一个异步调用
//如果想等数据更新后做一些操作,可以传入第二个参数:回调
//第二个参数执行的时机就是数据更新完之后
this.setState({
   
    name

网站公告

今日签到

点亮在社区的每一天
去签到