Hooks useContext
组件之间共享状态
React 的 Context API 是一种在应用程序中深入传递数据的方法,而无需手动一个一个在多个父子孙之间传递 prop。当需要的只是传递数据时,它可以提代redux,但是如果还需要共享方法,改变数据,那么使用redux可能是更好的选择
redux
react-redux具体可看另一篇介绍react基本使用得文章,里面详细提到了react-redux得使用。
props层级传递
要注意得是,props不仅可以传递属性参数还可以传递组件。
Context
Context 提供了一个无需为每层组件手动添加 props,就能在组件树间进行数据传递的方法。
Context 设计目的是为了共享那些对于一个组件树而言是“全局”的数据,例如当前认证的用户、主题或首选语言。
但是要慎用,因为可能会让组件得复用性变差。
页面传参,实时更新
获取数据
因为提到实时了,所以必然会有实时获取数据的问题,实时获取数据有两种方案:前端轮询和长连接,但是轮询是不可行的,过多的定时器会给页面带来很大压力,而且一直请求也会给服务器代来很大压力。那么就只有长连接。
长连接又有两种方案,websocket和sse,sse其实是轻量化的websocket,我使用的是sse.
sse的使用
下载:
yarn add event-source-polyfill
引用
import { NativeEventSource, EventSourcePolyfill } from "event-source-polyfill";
使用:
new EventSource() 里面放的是后端的请求地址,其他方法的含义在注释里都体现出来了。
//sse链接
let EventSource = NativeEventSource || EventSourcePolyfill;
// if (typeof EventSource !== "undefined" && !api) {
let eventSource = new EventSource(`xxx`);
eventSource.onmessage = e => {
console.log('消息推送')
}
eventSource.onclose = e => {
console.log("连接已关闭...");
};
eventSource.onerror = e => {
console.log("出错拉...");
};
eventSource.onopen = e => {
console.log("已连接...");
};
消息推送
消息推送这里有两种情况
- 第一种情况是react + iframe
就是指你的子页面是使用iframe,那么这种情况下,可以使用postMessage与addEventListenerde的结合。
也就是使用postMessage 传输信息,使用addEventListener(‘message’)监听信息的更新。
这里要注意的是,如果不是使用 window.open() 打开的页面或者 iframe 嵌入的页面,无法使用 window.postMessage() 进行跨域通信的。一个窗口可以获得对另一个窗口的引用(比如 targetWindow = window.opener),然后在窗口上调用 targetWindow.postMessage() 方法分发一个 MessageEvent 消息。 两个不同页面是无法获取对方的window的,因此无法使用postMessage通信。
使用:
each(document.body.getElementsByTagName("iframe"), iframe => {
iframe.contentWindow.postMessage(
{
operation: "schedule",
data: data.messageContent
},
window.location.origin
);
});
useEffect(() => {
window.self.addEventListener("message", onMessage, false);
return () => {
window.self.removeEventListener("message", onMessage, false);
};
}, []);
- 第二种情况就是普通的react单页面应用,这是用不了上述方法的,那么就要使用pubsub-js发布订阅模式
这种情况很简单也是大多数会遇到的情况。
使用:
发布
eventSource.onmessage = e => {
let data = JSON.parse(e.data);
Pubsub.publish('data2_1', data)
console.log('消息推送')
}
订阅
useEffect(() => {
Pubsub.unsubscribe('data2_1'); // 如果没有这里,会调用多次订阅函数
Pubsub.subscribe('data2_1', (msg, data) => {
console.log(msg) // 这里将会输出对应设置的 pubsubID
console.log(data) // 这里将会输出对应设置的参数
console.log('监听了嘿')
})
return () => {Pubsub.unsubscribe('data')} // 销毁订阅
}, [])