封装一个postMessage库,进行iframe跨域交互
herry菌 人气:1这是近期个人在开发chrome插件时的其中一个小总结。还有很多没有总结出来。因为目前插件还在迭代中,(herry菌插件,用于B站C站),属于个人业余的一个小项目。还有很多功能没有实现,以及还需要再看能加上什么功能。
封装的postMessage库 herryPostMessage.js
(function (w) { //herry对象 w.herry = {}; //iframe的id if(!herry.iframeId) { herry.iframeId = 'iframe' } //父窗口名字 if(!herry.parentName) { herry.parentName = '父窗口' } //子窗口名字 if(!herry.childName) { herry.childName = '子窗口' } //跨域对象 const messageObj = {}; //父页面 /** * 发送给子页面数据 */ const postMessage = (data, fn = null) => { const iframe = document.getElementById(herry.iframeId) iframe.contentWindow.postMessage( { name: herry.parentName, //父页面名字 ...data, }, "*" ); messageObj[data.action] = fn; }; /** * 监听子页面返回的数据 */ w.addEventListener( "message", (event) => { const { data } = event; if (data && typeof data === "object" && data.name === herry.childName) { messageObj[data.action](data); } }, false ); //子页面 /** * 返回数据给父页面 参1=当前action 参2=返回的数据 */ const returnData = (action, data) => { top.postMessage( { name: herry.childName, //子页面名字 action, data, }, "*" ); }; /** * 监听父页面发送的数据 */ w.addEventListener( "message", async (event) => { const { data } = event; if (data && typeof data === "object" && data.name === herry.parentName) { if (herry.callback) { herry.callback(data) } } }, false ); herry.postMessage = postMessage; herry.returnData = returnData; })(window);
使用这个库让a域名下获取b域名下的数据,即a发出请求,b返回给a数据。a是父页面,b是子页面
使用:
域名a和b的页面上都需要引入herryPostMessage.js
a页面处理(父页面):
加入iframe(src是b域名的页面,需要设置一个id,一般也可以将iframe使用样式隐藏掉)。
<iframe src="//b.com/xxx.html" id="ifr" frameborder="0" ></iframe>
设置iframeId=上面的这个id:
herry.iframeId = "ifr";
发起请求(action是设置的一个请求名,在b页面中进行匹配用。后面的数据是携带给b页面用的参数。后面的res是b页面执行后的回调函数,可进行处理b返回的数据):
herry.postMessage({ action:'geta1', x: 1 }, (res) => { console.log(res.data); });
b页面处理(子页面):
b页面的herry.callback通过action匹配执行,并做处理,通过herry.returnData将数据返回给a的回调函数。即实现了交互。
herry.callback = async (data) => { if (data.action === "geta1") { //... herry.returnData(data.action, { x: 2 }); } //... };
不过这种封装方式也不是特别好,有局限性,比如b(子页面)像a(父页面)发起请求还是比较麻烦。欢迎各位提出意见或建议。
加载全部内容