需求:需要在系统中嵌入一个子项目,同时父项目与子项目是分开部署,子项目需要拿到父项目的token以及一系列参数。
第一步:父项目: angular版
<iframe
width="100%"
style="min-height: calc(100vh - 70px);background: #ffffff"
frameborder="0" marginheight="0px"
sandbox="allow-top-navigation allow-scripts allow-same-origin"
id="workFlowIframe"
src="http://192.168.9.236:1024/">
</iframe>
在angular的初始化声明周期中加入对子项目的postMessage监听事件,当子项目发送message来时可以捕捉到
ngOnInit(): void {
this.postToIframe();
}
ngOnDestroy() {
console.log('destroy');
//在离开页面时必须手动清空数据,因js不会主动回收document全局对象
//如果用angular的viewChild去捕捉dom,js会主动回收
this.cleanup()
}
messageListener =null
postToIframe() {
const iframe: any = document.getElementById('workFlowIframe');
if (!iframe) {
return;
}
const token = this.getToken();
const businessType = this.getBusinessType();
const lang = this.getSystemLanguage();
const header = {}
if (businessType !== null) {
header['businessType'] = businessType;
}
header['authorization'] = token;
header['lang'] = lang;
this.messageListener = function(event) {
//175为线上环境,236为本地环境
if (event.origin !== 'http://192.168.199.175:1024' && event.origin !== 'http://192.168.9.236:1024') return;
if(event.data === 'recieved') {
console.log(1,event);
iframe.contentWindow.postMessage(header, '*');
}
}
window.addEventListener('message', this.messageListener, false);
}
cleanup() {
// 移除事件监听器
if (this.messageListener) {
window.removeEventListener('message', this.messageListener);
}
this.messageListener = null;
// 移除 iframe
const iframe: any = document.getElementById('workFlowIframe');
if (iframe) {
iframe.remove();
}
}
第二步: 在子项目(vue)的beforeMounted生命周期中发送给父项目message,告诉父项目自己已经可以接受数据
beforeMount() {
console.log('发送到父')
window.parent.postMessage('recieved', '*');
},
第三步: 当子项目发送的message被父项目接收到之后,父项目把参数用postMessage发送给子项目,子项目在main.js中监听
window.addEventListener('message', function(event) {
if (event.origin !== 'http://localhost:4200' && event.origin !== 'http://192.168.199.175:12121') return;
localStorage.setItem('header', JSON.stringify(event.data));
console.log(2,event);
store.commit('changeLang',event.data.lang)
locale.use(event.data.lang === 'en_US' ? enLocale : zhLocale)
}, false);
ps: 整体思路类似“握手”,保证了子项目能如期获取到数据,而不会发生在父项目发送之前导致消息错过,或者子项目的初始化请求前,导致请求来不及拿到请求头而导致请求失败。同时可以在父项目在任意初始化后的节点:例如token主动刷新,语言系统切换等情况再次主动发送postMessage到子项目。