React事件通信

1,426 阅读2分钟

写在前面

React组件之间的通信一般分为下面几种情况:

  • 父子组件之间的通信
  • 非嵌套组件之间的通信

父子组件之间的通信

这是最简单也是最常用的一种通信方式:父组件通过向子组件传递 props,子组件得到 props 后进行相应的处理。下面贴两段代码:

父组件 FatherComp.js:

import React from "react";
import Son from "./SonComp";

export default function FatherComp() {
  return (
    <div>
      <Son title="我就是高阶领主" />
    </div>
  );
}

子组件 SonComp.js:

import React from "react";

const Son = (props) => {
  return <h1>{props.title}</h1>;
};

export default Son;

这个也没啥好说的,最简单的透传,下面主要介绍非嵌套的组件之间的通信。

非嵌套组件之间的通信

简单来说就是组件之间没有什么关联,需要通信就需要有个媒介,这里我们采用自定义事件的方式来进行通信: 首先需要安装一个event包

npm install events --save

新建一个 event.js,引入 events 包,并向外提供一个事件对象,供通信时使用:

import { EventEmitter } from "events";
export default new EventEmitter();

App.js

import React from "react";
import "./styles.css";

import Comp1 from "./Comp1";
import Comp2 from "./Comp2";
import FatherComp from "./FatherComp";

export default function App() {
  return (
    <div>
      <FatherComp />
      <Comp1 />
      <Comp2 />
    </div>
  );
}

Comp1.js

import React, { useState, useEffect } from "react";
import emitter from "./event";

export default function Comp1() {
  const [msg, setMsg] = useState(null);
  useEffect(() => {
    // 声明一个自定义事件
    // 在组件装载完成以后
    this.eventEmitter = emitter.addListener("clickMe", (msg) => {
      setMsg(msg);
    });
    // 组件销毁前移除事件监听
    return () => {
      emitter.removeListener(this.eventEmitter);
    };
  }, []);

  return (
    <div>
      {msg}
      组件1
    </div>
  );
}

Comp2.js

import React from "react";
import emitter from "./event";

export default function Comp2() {
  const cb = () => {
    return () => {
      // 触发自定义事件
      emitter.emit("clickMe", "Hello");
    };
  };
  return (
    <div>
      组件2<button onClick={cb()}>点击我</button>
    </div>
  );
}

下面我们写一个简单的事件demo来深入了解一下:

    var eventPool = {
      map: {},
      // 事件订阅
      on: (name, cb) => {
        eventPool.map[name] = cb;
      },
      // 事件发射
      emit: (name, ...args) => {
        const cb = eventPool.map[name];
        cb && cb(...args);
      }
    };
    // xxx为事件名,有两个参数
    eventPool.on("xxx", (p1, p2) => console.log(p1, p2));
    // 发射完直接打印了这两个参数
    eventPool.emit("xxx", 1, 2);

总结

自定义事件在组件之间没有直接联系的情况下使用还是很方便的,总之就是香~ 这里是本篇文章涉及的代码,项目地址在 www.zhangzheyi1.com/2021/07/30/…