之前简单封装过一个旧版,主要是开发chrome插件时使用的。
旧库见文章:https://www.cnblogs.com/wuhairui/p/14595893.html
新版库主要做了下多个iframe和父页面交互的优化。主要使用构造函数的方式将多个iframe的交互使用多个对象进行区分,这样多个交互就可以互相独立了。
并可子页面主动调用传值给父页面。
新版代码:
/** * iframeId iframe的id * parentName 父窗口名,一般不改 * childName 子窗口名 多个iframe时需要使用 * postMessage 父窗口调用 需要子页面加载完成后才能执行到 * returnData 子窗口主动回应 * callback 父窗口调用后子窗口判断 */ (function (w) { function HerryPostMessage(iframeId = 'iframe') { this.iframeId = iframeId; this.parentName = '父窗口'; this.childName = '子窗口'; //跨域对象 this.messageObj = {}; /** * 监听父页面发送的数据 */ w.addEventListener( "message", async (event) => { const { data } = event; if (data && typeof data === "object" && data.name === this.parentName) { if (this.callback) { this.callback(data) } } }, false ); /** * 监听子页面返回的数据 */ w.addEventListener( "message", (event) => { const { data } = event; if (data && typeof data === "object" && data.name === this.childName) { if(this.messageObj[data.action]) { this.messageObj[data.action](data); } } }, false ); } //父页面 /** * 发送给子页面数据 */ HerryPostMessage.prototype.postMessage = function(data, fn = null) { const iframe = document.getElementById(this.iframeId) iframe.contentWindow.postMessage( { name: this.parentName, //父页面名字 ...data, }, "*" ); this.messageObj[data.action] = fn; }; //子页面 /** * 返回数据给父页面 参1=当前action 参2=返回的数据 */ HerryPostMessage.prototype.returnData = function(action, data) { top.postMessage( { name: this.childName, //子页面名字 action, data, }, "*" ); }; //抛出 w.HerryPostMessage = HerryPostMessage; })(window);
使用方法:
父子页面均引入herryPostMessage.js。
父页面:
引入子页面b1,设置一个id
<iframe id="b1" src="//localhost:8081/b1.html" frameborder="0"></iframe>
创建对象,参数传参为iframe的id,设置对象的childName也同名。
父子页面均加载后,调用对象的postMessage方法,传入action,data可传可不传。第二个参数为子页面的回调。
const b1 = new HerryPostMessage('b1') b1.childName = 'b1'; //此处需要延迟 因为到登录子页面加载完毕 setTimeout(() => { b1.postMessage({action:'geta',data: '父页面传给子页面的数据'},(res) => { console.log('父页面打印',res.data) }) },500)
子页面:
创建该页面的对象(一般和父页面创建的同名)
创建callback函数,做判断,父页面调用后,会进入到这里。处理后可以使用对象的returnData方法将数据传回给父页面的回调函数中。
const b1 = new HerryPostMessage('b1'); b1.childName = 'b1'; b1.callback = (data) => { if(data.action === 'geta') { //获取到父页面传来的数据 console.log('子页面打印',data.data) //子页面回传给父页面数据 b1.returnData('geta','子页面回传给父页面数据') } }
另外,在子页面中直接调用returnData也可以主动传回给父页面数据
setTimeout(() => { b1.returnData('geta','子页面主动传给父页面数据') },1000)