跨组件通信模式合集
本目录包含 7 种无第三方依赖 的跨组件通信模式实现。为了“保留各模式最合适的调用方式”,每种模式对外导出的 API 不强求一致(例如 EventBus 使用 on/emit,Store 使用 setState,ProxyStore 暴露 state)。
📋 模式总览
| # | 模式 | 核心文件 | 文档 | 特点 | 最佳场景 |
|---|---|---|---|---|---|
| 1 | 发布订阅 | SharedStateBridgeSingleton.ts | README | 完全解耦,多对多通信 | 工单系统、微前端 |
| 2 | 观察者 | ObserverSingleton.ts | README | 一对多依赖关系 | 数据驱动更新 |
| 3 | 事件总线 | EventBusSingleton.ts | README | 简单直接,on/emit | 全局事件通知 |
| 4 | 状态容器 | StoreSingleton.ts | README | 状态快照,批量更新 | 简单状态管理 |
| 5 | 广播通道 | BroadcastSingleton.ts | README | 跨标签页同步 | 多标签页/iframe |
| 6 | 自定义事件 | CustomEventSingleton.ts | README | 原生 DOM API | 跨框架通信 |
| 7 | 代理模式 | ProxyStoreSingleton.ts | README | 透明响应式操作 | Vue3/Valtio 风格 |
🔗 入口文件约定
每种模式都有一个 *Singleton.ts 作为默认入口(也会额外导出底层实例供高级用法)。
🎯 模式选择指南
┌─────────────────────────────────────────────────────────────────────┐
│ 如何选择通信模式? │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ 需要跨浏览器标签页通信? │
│ └── 是 → 广播通道 (BroadcastChannel) │
│ │
│ 需要跨框架通信(React + Vue + Angular)? │
│ └── 是 → 自定义事件 (CustomEvent) │
│ │
│ 需要透明响应式(类似 Vue3)? │
│ └── 是 → 代理模式 (ProxyStore) │
│ │
│ 需要状态快照/批量更新? │
│ └── 是 → 状态容器 (Store) │
│ │
│ 动态加载组件/微前端场景? │
│ └── 是 → 发布订阅 (ServiceRequest) │
│ │
│ 简单的全局事件通知? │
│ └── 是 → 事件总线 (EventBus) │
│ │
│ 一对多的数据依赖关系? │
│ └── 是 → 观察者 (Observer) │
│ │
└─────────────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
📁 目录结构
Pattern/
├── README.md # 本文档
│
├── ServiceRequest/ # 1. 发布订阅模式
│ ├── Registry.ts # 通用注册表
│ ├── SharedStateBridge.ts # 发布订阅核心类
│ ├── SharedStateBridgeSingleton.ts # 单例导出 ⭐
│ └── README.md # 使用文档
│
├── Observer/ # 2. 观察者模式
│ ├── Subject.ts # 被观察者核心类
│ ├── ObserverSingleton.ts # 单例导出 ⭐
│ └── README.md # 使用文档
│
├── EventBus/ # 3. 事件总线
│ ├── EventBus.ts # 事件总线核心类
│ ├── EventBusSingleton.ts # 单例导出 ⭐
│ └── README.md # 使用文档
│
├── Store/ # 4. 状态容器
│ ├── Store.ts # 状态容器核心类
│ ├── StoreSingleton.ts # 单例导出 ⭐
│ └── README.md # 使用文档
│
├── BroadcastChannel/ # 5. 广播通道
│ ├── BroadcastBridge.ts # 广播桥接核心类
│ ├── BroadcastSingleton.ts # 单例导出 ⭐
│ └── README.md # 使用文档
│
├── CustomEvent/ # 6. 自定义事件
│ ├── CustomEventBridge.ts # 自定义事件核心类
│ ├── CustomEventSingleton.ts # 单例导出 ⭐
│ └── README.md # 使用文档
│
└── ProxyStore/ # 7. 代理模式
├── ProxyStore.ts # 代理存储核心类
├── ProxyStoreSingleton.ts # 单例导出 ⭐
└── README.md # 使用文档
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
📊 模式对比
功能对比
| 特性 | 发布订阅 | 观察者 | 事件总线 | 状态容器 | 广播通道 | 自定义事件 | 代理模式 |
|---|---|---|---|---|---|---|---|
| 完全解耦 | ✅ | ⚠️ | ✅ | ✅ | ✅ | ✅ | ✅ |
| 多对多通信 | ✅ | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ |
| 跨标签页 | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ |
| 跨框架 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| 状态缓存 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| 状态快照 | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ✅ |
| 透明操作 | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ |
| 一次性订阅 | ❌ | ❌ | ✅ | ❌ | ❌ | ✅ | ❌ |
浏览器兼容性
| 模式 | Chrome | Firefox | Safari | Edge | IE |
|---|---|---|---|---|---|
| 发布订阅 | ✅ | ✅ | ✅ | ✅ | ✅ |
| 观察者 | ✅ | ✅ | ✅ | ✅ | ✅ |
| 事件总线 | ✅ | ✅ | ✅ | ✅ | ✅ |
| 状态容器 | ✅ | ✅ | ✅ | ✅ | ✅ |
| 广播通道 | 54+ | 38+ | 15.4+ | 79+ | ❌ |
| 自定义事件 | ✅ | ✅ | ✅ | ✅ | 9+ |
| 代理模式 | 49+ | 18+ | 10+ | 12+ | ❌ |
🔧 各模式详解
1️⃣ 发布订阅模式 (Pub/Sub)
📁 ServiceRequest/ | 📄 文档
核心文件:
- SharedStateBridge.ts - 发布订阅核心类
- SharedStateBridgeSingleton.ts - 单例导出
原理:通过中间调度中心解耦发布者和订阅者,支持多对多通信。
import {
publishSharedData,
subscribeSharedData
} from './ServiceRequest/SharedStateBridgeSingleton'
// 发布
publishSharedData('user.profile', { name: 'John' })
// 订阅
subscribeSharedData('user.profile', (data) => {
console.log('Profile updated:', data)
})
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
2️⃣ 观察者模式 (Observer)
核心文件:
- Subject.ts - 被观察者(Subject)类
- ObserverSingleton.ts - 单例导出
原理:被观察者维护观察者列表,状态变化时直接通知所有观察者。
import { subject } from './Observer/ObserverSingleton'
const counter$ = subject<number>('counter')
counter$.attach((value) => console.log(value))
counter$.notify(10)
1
2
3
4
5
2
3
4
5
vs 发布订阅:观察者直接依赖被观察者,发布订阅通过中间调度。
3️⃣ 事件总线 (Event Bus)
核心文件:
- EventBus.ts - 事件总线核心类
- EventBusSingleton.ts - 单例导出
原理:集中式事件管理,经典的 on/emit 模式。
import { on, emit, once } from './EventBus/EventBusSingleton'
// 一次性订阅
once('app:ready', () => {
console.log('App initialized!')
})
emit('app:ready', true)
// 普通订阅
on('app:ready', (ready) => console.log('ready?', ready))
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
4️⃣ 状态容器 (Singleton Store)
核心文件:
- Store.ts - 状态容器核心类
- StoreSingleton.ts - 单例导出
原理:单例状态对象 + 订阅机制,支持状态快照和批量更新。
import { setState, getSnapshot, batchUpdate } from './Store/StoreSingleton'
// 批量更新
batchUpdate({
'user.name': 'John',
'user.age': 30,
theme: 'dark'
})
// 单点更新
setState('user.name', 'John')
// 获取快照
console.log(getSnapshot())
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
5️⃣ 广播通道 (Broadcast Channel)
📁 BroadcastChannel/ | 📄 文档
核心文件:
- BroadcastBridge.ts - 广播桥接核心类
- BroadcastSingleton.ts - 单例导出
原理:浏览器原生 BroadcastChannel API,支持跨标签页通信。
import { publish, subscribe } from './BroadcastChannel/BroadcastSingleton'
// 标签页 A:发布
publish('session', { userId: 123 })
// 标签页 B:自动收到
subscribe('session', (session) => {
console.log('Session synced:', session)
})
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
⚠️ 注意:仅同源页面可通信,不支持 IE。
6️⃣ 自定义事件 (Custom Events)
📁 CustomEvent/ | 📄 文档
核心文件:
- CustomEventBridge.ts - 自定义事件核心类
- CustomEventSingleton.ts - 单例导出
原理:原生 DOM CustomEvent + dispatchEvent。
import { dispatch, on } from './CustomEvent/CustomEventSingleton'
// React 组件发布
dispatch('button:clicked', { from: 'react' })
// Vue 组件订阅
on('button:clicked', (data) => {
console.log('Received:', data)
})
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
适用:跨框架通信(React + Vue + Angular)、微前端。
7️⃣ 代理模式 (Proxy Store)
📁 ProxyStore/ | 📄 文档
核心文件:
- ProxyStore.ts - 代理存储核心类
- ProxyStoreSingleton.ts - 单例导出
原理:ES6 Proxy 拦截读写操作,自动触发响应。
import { state, watch } from './ProxyStore/ProxyStoreSingleton'
// Vue3 风格监听
watch(
() => state.count,
(value) => console.log('Count:', value),
{ immediate: true }
)
// 直接赋值,自动触发订阅
state.count = 10 // 输出: Count: 10
state.count++ // 输出: Count: 11
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
风格:类似 Vue 3 响应式 / Valtio。
🪝 React Hook 建议
由于各模式的 API 设计不同(这是刻意的),更推荐在业务侧针对“你选择的那种模式”写一个非常薄的 Hook 适配层。
