一、组件间通信
父组件与子组件
通过 Props(单向数据流)
父组件通过props
将数据传递给子组件。
子组件不能直接修改父组件的状态,只能通过触发事件或回调通知父组件。
适用场景: 父组件控制子组件的数据。
// 父组件
<ChildComponent data={this.state.data} onAction={this.handleAction} />
// 子组件
const ChildComponent = ({ data, onAction }) => {
return <button onClick={() => onAction('clicked')}>Click Me</button>;
};
2.通过 Ref(直接操作子组件)
父组件通过 ref
获取子组件实例,从而调用子组件的方法或访问其状态。
适用场景: 需要直接操作子组件,例如表单重置。
// 父组件
const parentRef = useRef();
<ChildComponent ref={parentRef} />;
parentRef.current.someMethod();
2.子组件与父组件
通过回调函数(事件回调)
子组件通过调用props
中传入的回调函数通知父组件。
适用场景: 子组件需要向父组件传递数据或事件。
const Parent = () => {
const handleChildAction = (value) => console.log(value);
return <Child onAction={handleChildAction} />;
};
const Child = ({ onAction }) => {
return <button onClick={() => onAction('value from child')}>Notify Parent</button>;
};
· 通过 Context
利用 React Context
提供的 Provider
和 Consumer
,可以实现父子组件之间的双向通信。
适用场景: 状态共享、深层嵌套组件通信。
const MyContext = React.createContext();
const Parent = () => (
<MyContext.Provider value={{ state, setState }}>
<Child />
</MyContext.Provider>
);
const Child = () => {
const { state, setState } = useContext(MyContext);
};
3.子组件与子组件(兄弟组件)
通过共同的父组件(状态提升)
兄弟组件共享一个父组件,通过父组件的状态和回调函数进行数据同步。
适用场景: 兄弟组件之间的数据交互。
const Parent = () => {
const [sharedData, setSharedData] = useState();
return (
<>
<ChildA setData={setSharedData} />
<ChildB data={sharedData} />
</>
);
};
const ChildA = ({ setData }) => <button onClick={() => setData('data from A')}>Send to B</button>;
const ChildB = ({ data }) => <div>{data}</div>;
·通过 Context 或 Redux
如果兄弟组件非常复杂或数据层级较深,Context
或状态管理工具(如 Redux、MobX)是更好的选择。
二、跨组件通信(非嵌套组件)
全局状态管理工具
Redux/MobX/Zustand/Recoil
将共享状态存储在全局管理工具中,组件可以订阅和更新状态。
适用场景: 跨组件的数据共享或复杂状态管理。
// Redux 示例
const mapStateToProps = (state) => ({ data: state.data });
const mapDispatchToProps = { setData };
connect(mapStateToProps, mapDispatchToProps)(Component);
2.Context API
通过 Context 提供跨层级共享数据
比 Redux 更轻量,但缺乏时间旅行等功能。适合简单的跨组件状态共享。
const DataContext = createContext();
<DataContext.Provider value={data}>
<ComponentA />
<ComponentB />
</DataContext.Provider>;
3.事件总线(EventEmitter)
自定义事件触发和监听
借助事件总线(如Node.js
的EventEmitter
或第三方工具),让组件可以跨层级监听事件。
适用场景: 复杂事件的广播或解耦需求。
const emitter = new EventEmitter();
emitter.on('event', () => console.log('event triggered'));
emitter.emit('event');
4.基于订阅-发布模式(Pub/Sub)
借助库(如 RxJS 或 PubSubJS)实现消息传递
适用场景: 解耦的多对多通信。
PubSub.subscribe('TOPIC', (_, data) => console.log(data));
PubSub.publish('TOPIC', 'some data');
三、跨系统通信
API 请求
- 通过 HTTP 请求(Axios/Fetch) 与后端服务器通信,获取或发送数据。 适用场景: 前后端通信、动态数据加载。
WebSocket
实现实时通信
通过WebSocket
实现全双工通信,常用于实时数据流。
适用场景: 实时聊天、在线协作。
const socket = new WebSocket('ws://example.com');
socket.onmessage = (event) => console.log(event.data);
3.iframe/postMessage
跨域通信
父页面与 iframe 之间通过postMessage
通信。
适用场景: 嵌套页面或第三方系统集成。
iframe.contentWindow.postMessage('message', '*');
window.addEventListener('message', (event) => console.log(event.data));
4.Service Worker
离线通信
使用Service Worker
处理离线缓存或推送通知。
适用场景: PWA(渐进式 Web 应用)。
navigator.serviceWorker.register('/sw.js');
总结:
- 简单层级通信: 优先用
props
和回调。 - 复杂层级通信: 考虑
Context
或全局状态管理。 - 跨组件通信: 使用 Redux 或事件总线。
- 实时或跨系统通信: 使用 WebSocket、API 或 iframe。