观察者模式
Subject 和 Observer 直接绑定,中间无媒介。如点击事件,事件直接和按钮进行绑定。
发布订阅模式
Publisher 和 Observer 相互不认识,中间有媒介。如在 A 组件中绑定一个事件,在 B 组件中触发这个事件,这个两个组件相隔十万八千里互补认识,那么就通过中间event这个媒介来通讯。
发布订阅模式需要在代码中触发 emit
,而观察者模式没有 emit
手写观察者模式
import React, { useState, useEffect } from 'react';
// 观察者函数
const observer = (newValue) => {
console.log(`Subject changed to ${newValue}`);
};
const SubjectComponent = () => {
// 使用useState创建一个状态变量
const [subject, setSubject] = useState('Initial Value');
// 使用useEffect来模拟观察者模式
useEffect(() => {
// 当subject变化时,调用观察者函数
observer(subject);
}, [subject]); // 依赖数组中包含subject,这样每当subject变化时,useEffect都会执行
// 更新subject的方法
const updateSubject = () => {
setSubject('Updated Value');
};
return (
<div>
<p>Subject: {subject}</p>
<button onClick={updateSubject}>Update Subject</button>
</div>
);
};
export default SubjectComponent;
手写发布订阅模式
// EventBus.js
import { createContext, useContext, useState } from 'react';
const EventBusContext = createContext();
export const EventBusProvider = ({ children }) => {
const [events, setEvents] = useState({});
const subscribe = (eventName, callback) => {
if (!events[eventName]) {
setEvents((prevEvents) => ({
...prevEvents,
[eventName]: [],
}));
}
setEvents((prevEvents) => ({
...prevEvents,
[eventName]: [...prevEvents[eventName], callback],
}));
};
const publish = (eventName, data) => {
if (events[eventName]) {
events[eventName].forEach((callback) => callback(data));
}
};
return (
<EventBusContext.Provider value={{ subscribe, publish }}>
{children}
</EventBusContext.Provider>
);
};
export const useEventBus = () => useContext(EventBusContext);