IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> reactHook实现EventBus -> 正文阅读

[JavaScript知识库]reactHook实现EventBus

目录

一、首先创建一个EventEmitter

二、events和useEventBus

三、使用events和useEventBus

1.同步调用

?2.异步调用


在开发react项目的时候,经常用到组件通信的场景,少不了EventBus,在ReactHook中如何使用EventBus呢?下面将详细介绍;

?

项目背景:本项目是基于react和TypeScript,其中主要是以ReactHook开发为主;

一、首先创建一个EventEmitter

新创建一个event-emitter.ts文件,在文件中放入如下代码:

import { pull } from 'lodash';

export type EventHandler<E = any> = (e: E) => void;

/*这个就是事件的原型*/
class EventEmitter<E = any> {
  private _events: Record<string, EventHandler<E>[]>;

  constructor() {
    this._events = {};
  }

  private _getFns(event: string) {
    return this._events[event] || (this._events[event] = []);
  }

  public on<T = E>(event: string, cb: EventHandler<T>) {
    const fns = this._getFns(event);
    fns.push(cb as any);
  }

  public off(event: string, cb?: EventHandler<E>) {
    if (cb) {
      const fns = this._getFns(event);
      pull(fns, cb);
    } else {
      delete this._events[event];
    }
  }

  public once<T = E>(event: string, cb: EventHandler<T>) {
    const fn2: EventHandler<E> = (e) => {
      this.off(event, fn2);
      cb(e as any);
    };
    this.on(event, fn2);
  }
  
  /* 同步调用 */
  public emit<T = E>(event: string, param?: T) {
    const fns = this._getFns(event);
    for (let i = 0; i < fns.length; i++) {
      const fn = fns[i] as EventHandler<any>;

      fn(param);
    }
  }

  /* 可以异步调用,返回一个Promise */
  public invoke<T = E>(event: string, param?: T): Promise<any> {
    const fns = this._getFns(event);

    flag: for (let i = 0; i < fns.length; i++) {
      const fn = fns[i] as EventHandler<any>;
      return new Promise<any>((resolve, reject) => {
        resolve(fn(param));
      });
      break flag;
    }
    return Promise.reject();
  }
}

export default EventEmitter;

二、events和useEventBus

创建events.ts文件,在文件中放入如下代码:

import EventEmitter, { EventHandler } from '@/common/event-emitter';
import { useEffect } from 'react';

const events = new EventEmitter();

export default events;

export function useEventBus<T = any>(
  event: string,
  cb: EventHandler<T>,
) {
  useEffect(() => {
    events.on(event, cb);
    return () => {
      events.off(event, cb);
    };
  });
}

三、使用events和useEventBus

现在有A组件和B组件,是两个没有任务关联的组件,无上下级关系的组件,要实现A组件向B组件传递数据,分为同步调用和异步调用两种情况,如下示例:

1.同步调用

同步调用的时候注意要用emit方法

  • A组件代码如下:
import React from 'react';
import { Button } from 'antd';
/*引用上文声明好的events*/
import { events } from "@/common/events";

const ADemo = () => {

  const handlePass = () => {
    /*emit第一个参数的名称要跟useEventBus的第一个参数名称保持一致,建议语义化深刻一点;而且系统内要保持唯一*/
    /*emit第二个参数,是传递给useEventBus的第二个参数所在函数的参数*/
    events.emit('get:a:params', '哈哈哈**');
  }

  return (
    <div>
      ADemo:
      <Button onClick={handlePass}>传递给B组件参数</Button>
    </div>
  );
};

export default ADemo;
  • B组件代码如下:
import React, { useState } from "react";
/*引用上文声明好的useEventBus*/
import { useEventBus } from "@/common/events";

const BDemo = () => {
  const [txt, setTxt] = useState<string>('');

  const handleReceive = (params: string) => {
    setTxt(params)
  }

  /* 对发出来的事件进行监听 */
  useEventBus('get:a:params', handleReceive);

  return (
    <div>
      BDemo接收到的参数:{txt || '空'}
    </div>
  );
};

export default BDemo;
  • A组件和B组件的页面效果如下:

在A组件中点击按钮,会把参数传递给B组件,在未点击前的状态如下:

?点击A组件中的按钮,B组件中接收到的参数如下:

?2.异步调用

异步调用要用invoke方法

  • ?A组件代码如下:
import React, { useState } from "react";
import { Button } from 'antd';
/*引用上文声明好的events*/
import { events } from "@/common/events";

const ADemo = () => {
  const [txt, setTxt] = useState<string>('');

  const handlePass = () => {
    /*emit第一个参数的名称要跟useEventBus的第一个参数名称保持一致,建议语义化深刻一点;而且系统内要保持唯一*/
    /*emit第二个参数,是传递给useEventBus的第二个参数所在函数的参数*/
    /*invoke方法返回一个promise,可以用then方法实现链式调用*/
    events.invoke('async:pass:params', '哈哈哈**').then(res => {
      setTxt(res)
    });
  }

  return (
    <div>
      ADemo:
      <Button onClick={handlePass}>传递给B组件参数</Button>
      <span style={{ marginLeft: 18 }}>B组件返回给A的结果:{txt || "空"}</span>
    </div>
  );
};

export default ADemo;
  • B组件代码
import React, { useState } from "react";
/*引用上文声明好的useEventBus*/
import { useEventBus } from "@/common/events";

const BDemo = () => {
  const [txt, setTxt] = useState<string>('');

  const handleReceive = (params: string) => {
    setTxt(params);
    return '我成功传递了数据';
  }

  /* 对发出来的事件进行监听 */
  useEventBus('async:pass:params', handleReceive);

  return (
    <div>
      BDemo接收到的参数:{txt || '空'}
    </div>
  );
};

export default BDemo;
  • A组件和B组件的页面效果如下:

在A组件中点击按钮,会把参数传递给B组件,在未点击前的状态如下:

在A组件中点击按钮之后,页面效果如下:

以上就是本次分享的全部内容了,欢迎参考呀!

  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2022-06-26 16:49:40  更:2022-06-26 16:51:39 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 13:48:36-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码