web-message-center v1.2.1
web-message-center
web 的消息中心插件
基于发布-订阅模式思想,利用 window.postMessage 封装的浏览器父子标签之间、父子页面、iframe 之间通信插件,消息名称及消息内容均可自定义
基础使用
在一个页面中引入
import WebMessageCenter from "web-message-center"
const wmc = new WebMessageCenter();
wmc.emit("message", {
from: "parent",
contents: "我是父页面",
});
在另外一个 iframe、页面中
import WebMessageCenter from "web-message-center"
const wmc = new WebMessageCenter();
wmc.on("message", function (data) {
console.log('form:'data.from + "contents" + data.contents);
});
api
constructor
const wmc = new WebMessageCenter(options)
options 参数是可选的,支持如下:
名称 | 类型 | 含义 |
---|---|---|
origin | String | 页面源,设置后只能在同一源(同一 url)下才能通信 * |
channel | String | 频道,处于同一频道下的 WebMessageCenter 才能相互通信 |
verifyDomain | Function | 校验发消息的来源,function (url) { return url.indexOf("https://my-domain") === 0; }, 只有返回 true 的时候才能接收到消息 |
targetFrames | Array | 给那些 iframe 发消息(Window (t window.open 的返回值) 或 HTMLFrameElement (iframe 元素)),也可以通过 wmc.addTargetFrame(myIframe);动态添加 |
target static
target(options),options 同上
// 只接收来自https://example.com的消息
wmc.target({ origin: 'https://example.com' }).on('message', () => {})
emit
emit('event', data?, reply?): boolean
参数 | 类型 | 描述 |
---|---|---|
event | String | 事件名称 |
data | Any | 传递的内容 |
callback | Function | 为订阅者提供的回调函数 |
on
on('event', fn): boolean
参数 | 类型 | 描述 |
---|---|---|
event | String | 事件名称 |
fn(data?, reply?) | Function | 事件处理函数,均来自于emit函数 |
once
触发回调后,立即注销监听,回调只触发一次
once('event', fn): boolean
参数 | 类型 | 描述 |
---|---|---|
event | String | 事件名称 |
fn(data?, reply?) | Function | 事件处理函数,均来自于emit函数 |
addTargetFrame
动态添加 targetFrames
include
动态添加 childWindow,即动态添加可广播 window
const newWin = window.open('https://example.com')
wmc.include(newWin)
off
off('event', fn): boolean
取消订阅
teardown
销毁实例
global
emit、on、once、off有对应的globalAPI,可以监听指定频道的通信、触发全局消息
API | 全局API |
---|---|
emit | emitGlobal |
on | onGlobal |
once | onceGlobal |
off | offGlobal |
yzw-helper
针对一张网业务场景,在web-message-center基础上提供扩展API
引入
import WebMessageCenter, { provide, inject, openTab } from 'web-message-center/dist/yzw-helper.mini.js'
const yzwHelper = new WebMessageCenter()
api
provide
构建WebMessageCenter对象,用于创建和指定子应用的私有通信频道,必须指明一个targetFrames
需要子应用配合使用inject API初始化
provide(options, props)
名称 | 类型 | 含义 |
---|---|---|
options | Object | 初始化参数,结构同构造函数参数 |
props | Object | 子应用加载初始化参数 |
options同构造函数,props为主应用传递的初始化数据
// 主应用
const options = {
channel: channel, // 可由主应用指定,不传时由组件内生成uuid
targetFrames: [iframeElement]
}
const props = {}; // 初始化参数
const wmc = WebMessageCenter.provide(options, props);
// 子应用,获取通信对象和初始化数据后渲染页面
inject((), (wmc, props) => {
render(wmc, props);
});
inject
使用init方法可获取和主应用的私有通信频道,配合主应用使用provide初始化时,可获取初始化数据
inject(options, initCallback)
名称 | 类型 | 含义 |
---|---|---|
options | Object | 初始化参数,结构同构造函数参数 |
initCallback | Function | 初始化回调函数,参数:wmc通信对象,props组件初始化参数 |
使用实例参考provide
openTab
应用需要打开浏览器新页签时,调用openTab方法,支持传入初始化数据
openTab(url, props)
名称 | 类型 | 含义 |
---|---|---|
url | String | 新页签地址 |
props | Object | 打开新页签传递初始化数据 |
子应用使用通信组件完整示例
qiankun
以qiankun官方Vue微应用示例为基础,罗列引入通信组件改动点
初始化:
// main.js
/**
* 1. 引入组件
* 2. 独立运行时,使用inject初始化(ie11使用iframe集成业务组件)
* 3. qiankun的mount方法,使用WebMessageCenter初始化
* 4. 改造render方法,将通信示例挂载到Vue实例上
*/
import './public-path'
import Vue from 'vue'
import VueRouter from 'vue-router'
import App from './App.vue'
import routes from './router'
import store from './store'
// 1. 引入组件
import { inject, default as WebMessageCenter } from 'web-message-center/dist/yzw-helper.mini.js'
Vue.config.productionTip = false
let router = null
let instance = null
// 4. 改造render方法,将初始化返回的方法或属性定义为全局属性
function render(wmc, props = {}) {
const { container } = props
// 方法或属性定义到Vue原型或通过其他方式,保证组件可以调用
Vue.prototype.$wmc = wmc
instance = new Vue({
router,
store,
render: (h) => h(App)
}).$mount(container ? container.querySelector('#app') : '#app')
}
// 独立运行时
if (!window.__POWERED_BY_QIANKUN__) {
// 2. 独立运行时,使用inject初始化(ie11使用iframe集成业务组件)
// 独立运行时,inject 相当于 new WebMessageCenter()
// 如果url里有channelKey,inject 相当于 new WebMessageCenter({channel: channelKeyValue })
inject({}, (wmc, props) => {
render(wmc, props)
})
}
export async function bootstrap() {
console.log('[vue] vue app bootstraped')
}
export async function mount(props) {
console.log('[vue] props from main framework', props)
// 3. qiankun的mount方法,使用WebMessageCenter初始化
const channel = props.name
inject({ channel }, (wmc, props) => {
render(wmc, props)
})
}
export async function unmount() {
instance.$destroy()
instance.$el.innerHTML = ''
instance = null
router = null
}
使用通信API:
// App.vue
<script>
export default {
mounted() {
// 组件渲染完毕后,通知父应用关闭遮罩
this.$wmc.emit({
info: {
_cmd: 'mounted'
}
})
// 监听换肤操作
this.$wmc.onGlobal('Msg_babgpt_customize-change', this.themeCallback)
},
methods: {
themeCallback(message) {
const theme = message.info?.windowOptions?.theme
// 执行换肤
}
}
}
</script>
非qiankun组件
非qiankun组件以iframe的方式嵌入,或window.open打开新页签,以vue举例。
// main.js
/**
* 1. 引入组件
* 2. 使用inject初始化
* 3. 改造render方法,将初始化返回的方法或属性定义为全局属性
*/
import Vue from 'vue'
import Router from 'vue-router'
import App from './App.vue'
import router from '@/router/index.js'
import { pinia, PiniaVuePlugin } from '@/plugins/pinia.js'
const app = new Vue({
router,
pinia,
render: (h) => h(App)
})
// 1. 引入组件
import { inject } from 'web-message-center/dist/yzw-helper.mini.js'
// 2. 使用inject初始化
const loadPage = inject({}, (wmc, props) => {
// 3. 改造render方法,将初始化返回的方法或属性定义为全局属性
// 方法或属性定义到Vue原型或通过其他方式,保证组件可以调用
Vue.prototype.$wmc = wmc
// props用于初始化操作
app.$mount('#app')
})
通信API的使用参考qiankun示例中的API使用。