iframe的缺点
如果不考虑体验问题,iframe 几乎是最完美的微前端解决方案了。
iframe 最大的特性就是提供了浏览器原生的硬隔离方案,不论是样式隔离、js 隔离这类问题统统都能被完美解决。但他的最大问题也在于他的隔离性无法被突破,导致应用间上下文无法被共享,随之带来的开发体验、产品体验的问题。
缺点:
- url不同步,浏览器刷新后页面丢失。
- UI不同步,dom结构不共享。比如弹窗居中问题。
- 全局上下文完全隔离,内存变量不共享。难以实现 iframe 内外系统的通信、数据同步等需求。
- 慢。每次子应用进入都是一次浏览器上下文重建,资源重新加载的过程。
<iframe src="xxxxx" id="xxxxx" name="xxxxx" ></iframe>
postMessage通信
otherWindow.postMessage(message, targetOrigin, [transfer]);
otherWindow:目标窗口(你想发送跨域消息的那个窗口),例如:iframe.contentWindowmessage将要发送的数据targetOrigin目标窗口的地址(URL),或者字符串*表示无限制、任何URL都允许发送
1.消息发送-子页面发给父页面
window.parent.postMessage('xxxxx','http://a.index.com');
2.消息发送-父页面发给子页面
contentWindow 属性返回当前HTMLIFrameElement的Window对象. 你可以使用这个Window 对象去访问这个iframe的文档和它内部的DOM. 这个是可读属性, 但是它的属性像全局Window 一样是可以操作的.
const iFrame = document.getElementById('iframe')<!-- 需要等到iframe中的子页面加载完成后才发送消息,否则子页面接收不到消息 -->iFrame.onload = function(){<!-- iFrame.contentWindow获取到iframe的window对象 -->iFrame.contentWindow.postMessage('xxx','*');}
3.消息接收-子父页面通用
if (typeof window.addEventListener != 'undefined') { // for ie9+、chromewindow.addEventListener('message', dealMessage, false);} else if (typeof window.attachEvent != 'undefined') { // for ie8-window.attachEvent('onmessage', dealMessage);}function dealMessage(e){// 对消息来源origin做一下过滤,避免接收到非法域名的消息导致的xss攻击if(e.origin==='http://a.index.com'){console.log(e.origin) //发送端页面URL,这里是http://a.index.comconsole.log(e.source) // 发送端window对象console.log(e.data) // 发送的消息}}
4.示例
const param = '{"id":1}';const message = '{"function":"func1","param":'+param+'}';window.parent.postMessage(message,'*');
//是否存在指定函数function isExitsFunction(funcName) {try {if (typeof(eval(funcName)) == "function") {return true;}} catch(e) {}return false;}//处理接收的消息function dealMessage(e){var obj = eval("("+e.data+")");if(isExitsFunction(obj["function"])){eval(obj["function"])(obj["param"]);}}//处理业务逻辑function func1(param){//...........}
引申:eval的用法 onload
window.parent 当前窗口的父窗口对象,如果没有返回自身window.top 顶层窗口对象window.frames 当前窗口的所有直接子窗口
