1. 设计架构
- 使用React的Context:Context 提供了一种在组件之间共享数据的方式,而无需在组件树中通过 props 层层传递。
- 自定义事件处理:在最内层组件触发自定义事件,通过 Context 将事件传递到最外层组件。
- 中间层处理:中间层组件可以通过 Context 订阅事件,对事件数据进行处理后再传递给下一层。
2. 实现代码
import React, { createContext, useState, useEffect } from'react';
// 创建Context
const CustomEventContext = createContext();
// 最内层组件
const InnerComponent = () => {
const { onCustomEvent } = React.useContext(CustomEventContext);
const handleClick = () => {
const eventData = { message: 'This is a custom event from inner component' };
onCustomEvent(eventData);
};
return (
<button onClick={handleClick}>Trigger Custom Event</button>
);
};
// 中间层组件(假设需要处理事件数据)
const MiddleComponent = () => {
const { onCustomEvent } = React.useContext(CustomEventContext);
useEffect(() => {
const handleInnerEvent = (data) => {
// 处理事件数据,例如添加时间戳
const newData = { ...data, timestamp: new Date().getTime() };
onCustomEvent(newData);
};
// 订阅事件
if (onCustomEvent) {
onCustomEvent.subscribe(handleInnerEvent);
}
return () => {
// 取消订阅
if (onCustomEvent) {
onCustomEvent.unsubscribe(handleInnerEvent);
}
};
}, [onCustomEvent]);
return (
<div>
<InnerComponent />
</div>
);
};
// 最外层组件
const OuterComponent = () => {
const [eventData, setEventData] = useState(null);
const customEventEmitter = {
handlers: [],
subscribe: (handler) => {
this.handlers.push(handler);
},
unsubscribe: (handler) => {
this.handlers = this.handlers.filter(h => h!== handler);
},
emit: (data) => {
this.handlers.forEach(handler => handler(data));
}
};
const handleCustomEvent = (data) => {
setEventData(data);
};
return (
<CustomEventContext.Provider value={{ onCustomEvent: customEventEmitter }}>
<div>
<h1>Outer Component</h1>
{eventData && (
<div>
<p>Received Event Data: {JSON.stringify(eventData)}</p>
</div>
)}
<MiddleComponent />
</div>
</CustomEventContext.Provider>
);
};
export default OuterComponent;
3. 性能优化
- 使用 React.memo:对于中间层组件和最内层组件,如果它们的 props 没有变化,可以使用
React.memo
包裹,避免不必要的渲染。例如:
const InnerComponent = React.memo(() => {
// 组件内容
});
const MiddleComponent = React.memo(() => {
// 组件内容
});
- 减少 Context 更新频率:在最外层组件中,尽量将
onCustomEvent
相关逻辑提取到一个单独的对象中,并保持该对象引用稳定,避免因为对象重新创建导致 Context 更新,进而引发不必要的渲染。如上述代码中 customEventEmitter
的设计。
- 事件订阅与取消:在中间层组件中,使用
useEffect
进行事件订阅和取消,确保在组件卸载时取消订阅,避免内存泄漏,同时减少不必要的事件处理重复执行。