🌒

Hi,

事件总栈

前端开发都会遇到一个老生常谈的场景,如下:
多组件、父子组件、孙子爷爷太爷爷组件如何进行互相的数据交互?


TL;DR


前言

所谓事件总栈就是一个集中管理和发布订阅的函数,通俗的讲就是发布订阅模式,接下来介绍一个react中个人用的比较多的三方库。如果想了解什么是发布订阅模式可以看我的这篇文章

useEventEmitter

拿React下Ahooks库提供的useEventEmitter来说:

使用方式

组件A(父)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
export const MainView: React.FC = () => {

const ctx$ = useEventEmitter()
ctx$.useSubscription((opt) => {
const {type, payload} = opt
if (type === 'jump') {
console.log(`${payload.name} jump`)
return
}
if (type === 'pay') {
console.log(`pay ${payload.currency}`)
return
}
...
})

return (
<>
<Child1 ctx={ctx$}></Child>
<Child2 ctx={ctx$}></Child>
</>
)
}

其他组件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
export const Child1: React.FC = ({ctx}) => {

const handleBtnClick = () =>{
ctx.emit({
type: 'jump',
payload: {
name: 'Mike'
}
})
}

return (
<>
<Button>Press Me</Button>
</>
)
}

如上

当然,在子组件和孙子组件中也可以直接坚挺emit事件,只需要在写上ctx.useSubscription即可,例如

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
export const Child2: React.FC = ({ctx}) => {

const handleBtnClick = () =>{
// 发送订阅
ctx.emit({
type: 'pay',
payload: {
currency: 20.22
}
})
}

// 事件订阅
ctx$.useSubscription((opt) => {
const {type, payload} = opt
if (type === 'jump') {
console.log(`${payload.name} jump`)
return
}
}

return (
<>
<Button>Press Me</Button>
</>
)
}

不过在使用的时候注意控制好订阅者,不要滥用,以免出现重复监听的问题。「到时追悔莫及,debug一百年」

👋 ;

, — 2025年4月20日