需求:
- 在一个页面下有多个子tab
- 在某些tab 下,或者父节点的数据更新的时候,其他子tab 或者父节点也要同步更新
进程:文章来源:https://www.toymoban.com/news/detail-699130.html
- 正常情况下会把所有用到的数据都移动到父节点,修改行为也都放在父节点
- 但如果这样的话父节点的数据会非常的多,而且有可能只是某两个子节点的数据需要更新,这就很麻烦
- 换一个思路,所有的数据都放在各自子节点但是,在某个变化发生的时候,触发一下更新逻辑
- 那又回到之前的那个问题了,需要每一个子节点都传入对应的触发函数
- 再换一个逻辑,增加一个全局的hook 并绑定上对应的事件,在你想要触发更新的时候调用一下这个hook 行为,如果有绑定的事件的话,就会触发对应事件
//eventhook
type eventName = string | Symbol
const eventMap = new Map<eventName, Array<Function>>()
const addListenerByName = (name: eventName, func: Function) => {
if (typeof func !== 'function') {
return ;
}
const listeners = eventMap.get(name) || []
if (!listeners.includes(func)) {
eventMap.set(name, [...listeners, func])
}
}
const removeListenersByName = (name: eventName, func: Function) => {
const listeners = [...(eventMap.get(name) || [])]
eventMap.set(name, listeners.filter(f => f !== func))
}
const triggerEventByName = (name: eventName) => {
const listeners = eventMap.get(name) || []
listeners.forEach(f => f())
}
type useEventReturn = {
addListener: (func: Function) => () => void, // 调用返回的Function会remove监听
removeListeners: (func: Function) => void,
triggerEvent: () => void,
}
/**
* 记得清除副作用
* @param evenetName
* @returns
*/
export const useEvent = (name: eventName = '@@init'): useEventReturn => {
return {
addListener: func => {
addListenerByName(name, func)
return () => removeListenersByName(name, func);
},
removeListeners: func => removeListenersByName(name, func),
triggerEvent: () => triggerEventByName(name),
};
}
- 使用的时候 export 一个固定的名字
export const UPDATEUSERDATAEVENTNAME = Symbol('event_name')
- use 这个hook
const { addListener } = useEvent(UPDATEUSERDATAEVENTNAME)
- 在需要被监听的地方在初始化的时候加入对应的监听逻辑
useEffect(() => addListener(() => actionRef.current?.reload()), [])
- 在需要触发这个监听逻辑的地方加入
const { triggerEvent } = useEvent(UPDATEUSERDATAEVENTNAME)
- 并触发这个监听
useEffect(() => {
triggerEvent()
}, [userId] )
- 这个做法的好处是就不需要往子组建传一堆东西了,而且也做到了更好的解耦
拓展文章来源地址https://www.toymoban.com/news/detail-699130.html
- 在使用这个方法的时候需要一个全局唯一的名字所以用到了 Symbol
- Symbol是一个绝对唯一的常亮,极端的例子 Symbol(“test”) != Symbol(“test”)
到了这里,关于react 实现监听逻辑的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!