Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/xxxily/broadcast-message
基于postMessage+BroadcastChannel+localStorage+互信域名的前端页面数据通信解决方案
https://github.com/xxxily/broadcast-message
broadcast broadcastchannel broadcastmessage cross-domain crosstab ipc localstorage postmessage
Last synced: 12 days ago
JSON representation
基于postMessage+BroadcastChannel+localStorage+互信域名的前端页面数据通信解决方案
- Host: GitHub
- URL: https://github.com/xxxily/broadcast-message
- Owner: xxxily
- License: mit
- Created: 2022-11-16T08:55:19.000Z (about 2 years ago)
- Default Branch: main
- Last Pushed: 2022-12-14T06:36:53.000Z (almost 2 years ago)
- Last Synced: 2024-04-27T17:22:29.240Z (7 months ago)
- Topics: broadcast, broadcastchannel, broadcastmessage, cross-domain, crosstab, ipc, localstorage, postmessage
- Language: JavaScript
- Homepage: https://broadcast-message.anzz.top
- Size: 1.15 MB
- Stars: 5
- Watchers: 2
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# broadcast-message
![broadcast-message](/logo.png)
> 基于postMessage+BroadcastChannel+localStorage+互信域名的前端页面数据通信解决方案
## 特性
- 继承了BroadcastChannel通信的优点:支持跨TAB通信
- 继承了localStorage通信的优点:兼容性好
- 继承了postMessage通信的优点:支持跨域通信
- 一套脚本解决前端数据通信面临的众多情况
- 支持同页、弹窗页、父子嵌套页、跨域、跨TAB页的通信## 安装
```sh
# npm
npm install broadcast-message# yarn
yarn add broadcast-message
```中国大陆用户可使用阿里源进行加速安装
```sh
# npm
npm install broadcast-message --registry=https://registry.npmmirror.com# yarn
yarn add broadcast-message --registry=https://registry.npmmirror.com
```## 使用
### 同域下基本使用示例
```javascript
import BroadcastMessage from 'broadcast-message'const bmOpts = { channelId: 'demo', allowLocalBroadcast: true }
const broadcastMessage = new BroadcastMessage(bmOpts)/* 注册接收消息事件 */
broadcastMessage.addEventListener("message", event => {
console.log(`[BroadcastMessage-Event]`, event.data)
})/* 发送消息 */
broadcastMessage.postMessage(`[demo] ${Date.now()}`)
```### 指定使用`localStorage`来中转消息
```javascript
import BroadcastMessage from 'broadcast-message'const bmOpts = { channelId: 'localStorage-demo', allowLocalBroadcast: true, transportType: 'localStorage' }
const broadcastMessage = new BroadcastMessage(bmOpts)/* 注册接收消息事件 */
broadcastMessage.addEventListener("message", function (event) {
console.log(`[BroadcastMessage-Event]`, event.data)
})/* 发送消息 */
broadcastMessage.postMessage(`[localStorage-demo] ${Date.now()}`)
````PS: 一般不建议手动指定transportType类型,broadcast-message默认会根据浏览器的支持情况自动选择BroadcastChannel还是localStorage,另外你应该了解的是:BroadcastChannel的通信效率比localStorage高`
### 跨域下基本使用示例
假设:
- 域名A是消息接收方
- 域名B是消息发送方域名A的代码示例:
```javascript
import BroadcastMessage from 'broadcast-message'const bmOpts = {
channelId: 'cross-domain-demo',
/* 必须使用可信域下的broadcast-message页来进行消息的中转,后面会介绍如何自定义可信域页面地址 */
trustedDomainPages: 'https://broadcast-message.anzz.top/dist/pages/broadcast-message.html',/* 指定接收来自哪个域名发送过来的消息,*表示信任所有域名的消息,生产环境推荐必须指定具体域名 */
// targetOrigin: "https:anzz.top"
targetOrigin: "*"
}const broadcastMessage = new BroadcastMessage(bmOpts)
/* 注册接收消息事件 */
broadcastMessage.addEventListener("message", event => {
console.log(`[BroadcastMessage-Event]`, event.data)
})
```域名B的代码示例:
```javascript
import BroadcastMessage from 'broadcast-message'const bmOpts = {
channelId: 'cross-domain-demo',
/* 可信域消息中转页的地址必须和域名A定义的一致 */
trustedDomainPages: 'https://broadcast-message.anzz.top/dist/pages/broadcast-message.html',
}
const broadcastMessage = new BroadcastMessage(bmOpts)/* 发送消息 */
broadcastMessage.postMessage(`[cross-domain-demo] ${Date.now()}`)
```附注:当进行跨域通信时,需先确认域名A和域名B的页面都已加载,且都完成了broadcast-message的初始化工作,才能开始通信,否则会出现消息发送出去了,但接收方还没准备好等情况,导致消息通信失败
### 自定义可信域页面
对于有跨域通信需求的项目,加载一个可信域的页面作为消息中转页是必不可少的。默认可以使用项目的自带可信域页面:
但出于下面的原因你可能需要自定义可信域页面
- 需要更快更稳定的可信域页面
- 项目对第三方网址有严格的限定
- 封装内部使用的跨域消息通信库自定义可信域页面代码示例如下:
```javascript
import BroadcastMessage from 'broadcast-message'
new BroadcastMessage({
/* 只需标识当前脚本运行在可信域页面内即可 */
inTrustedDomainPages: true,
})
```将初始化了`inTrustedDomainPages`选项的页面发布出去,即可获得一个自定义可信域页面
附注:为了让自定义可信域页面更快地加载,你应该务必不要掺杂其他无关逻辑进去,它只作为消息中转页面存在,并不需要其他额外内容
## broadcast-message选项
`new BroadcastMessage(opts)` 中的opts是一个对象它包含的选项和具体说明如下:
```javascript
const bmOpts = {
/**
* 指定BroadcastMessage的消息频道id,不同BroadcastMessage实例,只要channelId一致即可通信
* 默认的channelId为"*" , 这意味着在不指定频道id的情况下,各个实例的消息都会发往同一个频道上
*/
channelId: '*',/**
* 允许既是消息的发送页,也可以是消息的接收页,从而做到同源同页收发消息
* postMessage、BroadcastChannel和storage事件都是必须一个页面发送,另一个页面接收
* 而BroadcastMessage允许同页面收发消息,只需将allowLocalBroadcast设为true即可
*/
allowLocalBroadcast: false,/**
* 给 broadcastMessage.addEventListener("message", function (event) {}) 事件派发原始消息对象
* 默认情况下,broadcastMessage.postMessage(msg) 中的 msg 等于接收到的 event.data,但其实为了能准确派送消息,
* msg会被包装成有很多辅助参数的对象,如果你需要这些辅助参数信息,可以将emitOriginalMessage设为true
* 则收到的event.data将是如下的对象实体:
* event.data = {
* data: msg, // 消息本体
* type: 'BroadcastMessage', // 消息类型,默认为BroadcastMessage,其他类型,则是自定义消息或内部消息
* origin: '', // 消息来源的域名地址
* targetOrigin: '', // 消息目标源的域名地址
* referrer: '', // 消息来自哪个页面
* timeStamp: '', // 消息发出时的时间戳
* transportType: '', // 中转消息的载体类型,只可能为BroadcastMessage和localStorage
* allowLocalBroadcast: false, // 该消息是否允许被同页面的BroadcastMessage实例接收到
* channelId: '*', // 消息所属的频道id
* instanceId: 'xx_xx', // 消息所属BroadcastMessage实例id
* debug: false // 是否为开启了调试选项的消息
* }
*/
emitOriginalMessage: false,/**
* 指定消息发送的目标域,规则跟postMessage的targetOrigin一样
* 但不同的是支持定义数组形式的targetOrigin,从而实现批量跨域数据发送
* 当然如果是"*"的话就是给任意运行了本插件的页面发送数据
* 默认为 `location.origin`,即只可以在同域名的页面之间进行通信
*/
targetOrigin: location.origin,/**
* 指定数据中转传输使用的传输类型,可选值:BroadcastChannel、localStorage
* 不指定的话,优先使用BroadcastChannel,在不兼容BroadcastChannel的浏览器下使用localStorage
* 无特需情况,不建议修改该项配置
*/
transportType: 'BroadcastChannel',/**
* 标识BroadcastMessage实例是否处于可信域的页面上运行
* 如果是,当前页面作为可信域的中介页嵌入到具体运行环境中
* 该选项只在自定义可信域页面中使用,其他情况不要使用
*/
inTrustedDomainPages: false,/**
* 指定作为消息中转的可信域页面地址,有需跨域通信需求才会用到该选项
* 官方提供的可信域页面地址为:
* https://broadcast-message.anzz.top/dist/pages/broadcast-message.html
*/
trustedDomainPages: '',/* 标识是否开启调试选项 */
debug: false,
}
```## broadcast-message方法
broadcast-message实例包含的方法如下:
- addEventListener
- onMessage
- removeEventListener
- offMessage
- postMessage
- ready
- close下面对各个函数的使用方式进行逐一说明:
### addEventListener
函数参数:
- type {String} 必选,必须为 'message'
- listener {Function} 必选添加消息事件的侦听器
```javascript
import BroadcastMessage from 'broadcast-message'
const broadcastMessage = new BroadcastMessage({...opts})broadcastMessage.addEventListener('message', event => {
console.log(`[BroadcastMessage-Event]`, event.data)
})
```### onMessage
函数参数:
- handler {Function} 必选
添加消息处理函数,addEventListener是基于onMessage的,只是为了让BroadcastMessage保持跟BroadcastChannel一致的函数调用方式,所以增加了addEventListener事件
```javascript
import BroadcastMessage from 'broadcast-message'
const broadcastMessage = new BroadcastMessage({...opts})broadcastMessage.onMessage(event => {
console.log(`[BroadcastMessage-Event]`, event.data)
})
```### removeEventListener
函数参数:
- type {String} 必选,必须为 'message'
- listener {Function} 必选移除消息事件的侦听器
```javascript
import BroadcastMessage from 'broadcast-message'
const broadcastMessage = new BroadcastMessage({...opts})const listener = event => { console.log(`[BroadcastMessage-Event]`, event.data) }
broadcastMessage.addEventListener('message', listener)/* 一段时间后移除消息事件侦听器 */
setTimeout(() => { broadcastMessage.removeEventListener('message', listener) }, 3000)
```### offMessage
函数参数:
- handler {Function} 必选
移除消息处理函数,removeEventListener是基于onMessage的,只是为了让BroadcastMessage保持跟BroadcastChannel一致的函数调用方式,所以增加了removeEventListener事件
```javascript
import BroadcastMessage from 'broadcast-message'
const broadcastMessage = new BroadcastMessage({...opts})const handler = event => { console.log(`[BroadcastMessage-Event]`, event.data) }
broadcastMessage.onMessage(handler)/* 一段时间后移除消息事件处理函数 */
setTimeout(() => { broadcastMessage.offMessage(listener) }, 3000)
```### postMessage
函数参数:
- message {String|Number|Array|Object} 必选,必须为 'message'
- messageType {String} 可选 默认为'BroadcastMessage', 内部消息为:'Internal-BroadcastMessage', 一般不需传入该参数发送消息
```javascript
import BroadcastMessage from 'broadcast-message'
const broadcastMessage = new BroadcastMessage({...opts})
broadcastMessage.postMessage('test')
```### ready
函数参数:
- handler {Function} 必选 BroadcastMessage实例创建就绪后的回调函数
侦听BroadcastMessage实例创建就绪后,再执行响应的回调操作,因为BroadcastMessage初始化会创建消息中转的iframe,需要一定的创建时间,所以并不是拥有了BroadcastMessage实例就可以马上postMessage,而是要等到实例就绪才会将消息传送出去
默认情况下,在执行postMessage前,会自动检测BroadcastMessage实例是否完全就绪,如果没有会将需要发送的消息缓存起来,等BroadcastMessage实例创建就绪之后才将缓存的消息发送出去
```javascript
import BroadcastMessage from 'broadcast-message'
const broadcastMessage = new BroadcastMessage({...opts})broadcastMessage.ready(() => {
broadcastMessage.postMessage('test')
})// 如果没使用ready函数,直接调用postMessage也是没问题的
// 这是因为BroadcastMessage会自动判断实例是否创建就绪
// broadcastMessage.postMessage('test')
```### close
函数参数:
- 无
需要销毁BroadcastMessage实例时调用的函数,该函数会将BroadcastMessage中转所需的iframe、BroadcastChannel实例和通过addEventListener或onMessage定义的消息函数销毁掉
```javascript
import BroadcastMessage from 'broadcast-message'
let broadcastMessage = new BroadcastMessage({...opts})broadcastMessage.onMessage(event => { console.log(`[BroadcastMessage-Event]`, event.data) })
broadcastMessage.postMessage('test')/* 一段时间后销毁broadcastMessage实例 */
setTimeout(() => {
broadcastMessage.close()
broadcastMessage = null
}, 3000)
```