You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React中是否存在类似Laravel的事件分发与监听机制?

React生态中的自定义事件分发与监听方案

你正在学习Laravel框架,觉得它的事件分发与监听实现很有趣,之前用过Electron的类似系统但体验不如Laravel,想知道React生态里有没有等价的机制——不是监听DOM事件的addEventListener,而是像你给出的Laravel示例那样,实现组件间的自定义事件通信:

Laravel示例代码:

// 订阅事件:在Feed组件中
#[On('tweet-created')]
public function fetchTweets()
{
    $this->tweets = Tweet::with('user')
        ->latest()
        ->get();
}
// 分发事件:在CreateTweet组件中,当新推文创建时触发
$this->dispatch('tweet-created');

下面是React生态中对应的几种实现方式:

一、React内置方案(无需第三方依赖)

可以通过Context + 自定义逻辑封装一个轻量的事件总线,实现跨组件的事件订阅与分发:

1. 创建事件总线Context

// EventBusContext.jsx
import { createContext, useContext, useReducer, useCallback } from 'react';

const EventBusContext = createContext();

// 事件处理的reducer
const eventReducer = (state, action) => {
  switch (action.type) {
    case 'SUBSCRIBE':
      return {
        ...state,
        [action.eventName]: [...(state[action.eventName] || []), action.callback]
      };
    case 'UNSUBSCRIBE':
      return {
        ...state,
        [action.eventName]: (state[action.eventName] || []).filter(cb => cb !== action.callback)
      };
    case 'EMIT':
      (state[action.eventName] || []).forEach(cb => cb(action.payload));
      return state;
    default:
      return state;
  }
};

export const EventBusProvider = ({ children }) => {
  const [state, dispatch] = useReducer(eventReducer, {});

  // 订阅事件
  const subscribe = useCallback((eventName, callback) => {
    dispatch({ type: 'SUBSCRIBE', eventName, callback });
    // 返回取消订阅的函数
    return () => dispatch({ type: 'UNSUBSCRIBE', eventName, callback });
  }, [dispatch]);

  // 分发事件
  const emit = useCallback((eventName, payload) => {
    dispatch({ type: 'EMIT', eventName, payload });
  }, [dispatch]);

  return (
    <EventBusContext.Provider value={{ subscribe, emit }}>
      {children}
    </EventBusContext.Provider>
  );
};

// 自定义Hook,方便组件使用
export const useEventBus = () => useContext(EventBusContext);

2. 在组件中使用

// Feed组件:订阅事件
import { useEffect } from 'react';
import { useEventBus } from './EventBusContext';

function Feed() {
  const { subscribe } = useEventBus();

  useEffect(() => {
    // 订阅`tweet-created`事件,对应Laravel的#[On('tweet-created')]
    const unsubscribe = subscribe('tweet-created', () => {
      fetchTweets(); // 这里执行你的拉取推文逻辑
    });

    // 组件卸载时取消订阅,避免内存泄漏
    return unsubscribe;
  }, [subscribe]);

  const fetchTweets = async () => {
    // 模拟Laravel中的Tweet查询逻辑
    const res = await fetch('/api/tweets/latest');
    const tweets = await res.json();
    // 更新组件内的tweets状态
    // setTweets(tweets);
  };

  return <div> {/* 渲染推文列表 */} </div>;
}
// CreateTweet组件:分发事件
import { useEventBus } from './EventBusContext';

function CreateTweet() {
  const { emit } = useEventBus();

  const handleSubmit = async () => {
    // 模拟创建推文的API请求
    await fetch('/api/tweets', { method: 'POST', body: /* 推文数据 */ });
    
    // 分发`tweet-created`事件,对应Laravel的$this->dispatch('tweet-created')
    emit('tweet-created');
  };

  return <button onClick={handleSubmit}>发布推文</button>;
}

二、第三方库方案

如果不想自己封装,轻量级的事件库可以快速实现需求:

1. 使用mitt

mitt是一个只有200B大小的事件发射器,用法简洁:

npm install mitt
// 创建全局事件总线实例
// eventBus.js
import mitt from 'mitt';
export const eventBus = mitt();
// Feed组件中订阅事件
import { useEffect } from 'react';
import { eventBus } from './eventBus';

function Feed() {
  useEffect(() => {
    const handler = () => fetchTweets();
    eventBus.on('tweet-created', handler);
    
    return () => eventBus.off('tweet-created', handler);
  }, []);

  const fetchTweets = async () => { /* 拉取推文逻辑 */ };

  return <div> {/* 渲染列表 */} </div>;
}
// CreateTweet组件中分发事件
import { eventBus } from './eventBus';

function CreateTweet() {
  const handleSubmit = async () => {
    await fetch('/api/tweets', { method: 'POST' });
    eventBus.emit('tweet-created');
  };

  return <button onClick={handleSubmit}>发布推文</button>;
}

2. 使用tiny-emitter

tiny-emitter也是轻量的事件库,API类似Node.js的EventEmitter:

npm install tiny-emitter
// eventBus.js
import Emitter from 'tiny-emitter';
export const eventBus = new Emitter();
// Feed组件订阅
eventBus.on('tweet-created', () => fetchTweets());
// 取消订阅
eventBus.off('tweet-created', handler);

// CreateTweet组件分发
eventBus.emit('tweet-created');

这些方案都能实现你需要的、类似Laravel的组件间自定义事件通信,不需要依赖DOM事件系统。

内容的提问来源于stack exchange,提问作者Yusuf Bouzekri

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 15:39:55