我有一个iframe中的这个代码:
window.addEventListener('message',function(e){ if(e.data == 'test') console.log(e); },false);
而这里面的父文档:
$('#the_iframe').get(0).contentWindow.postMessage('test','http://localhost/');
所以父文档向iframe发送一个“测试”消息,它可以工作.
但是,如何在父文档中定义一个函数,并以某种方式通过postMessage将此函数发送到iframe,这将在本地执行该函数?
该函数对文档进行了一些更改:
var func = function(){ $("#some_div").addClass('sss'); }
(#some_div存在于iframe中,而不是父文档)
解决方法
没有什么会阻止你传递一个字符串函数作为postmessage事件数据.对于任何函数声明,实现是微不足道的
function doSomething(){ alert("hello world!"); }
你可以编码它的字符串解释:
console.log(encodeURI(doSomething.toString())); //function%20doSomething()%20%7B%0A%20%20%20%20alert(%22hello%20world!%22);%0A%7D
然后它可以作为关闭的一部分执行 – 这不是过分的想象力
eval('('+decodeURI(strCallback)+')();');
有一个fiddle’d proof of concept没有跨架架构 – 我会看看我是否可以放在一起postMessage版本,但是主持w / jsfiddle是不重要的
更新
如所承诺的,一个完整的模型,工作(链接下面).使用正确的event.origin检查,这将是非常透明的,但我知道,我们的安全团队永远不会让eval进行生产,像这样:)
给定选项我建议功能在两个页面之间归一化,这样只需要传递参数消息(即传递参数不是函数);然而,绝对有几种情况,这是首选方法.
父代码:
document.domain = "fiddle.jshell.net";//sync the domains window.addEventListener("message",receiveMessage,false);//set up the listener function receiveMessage(e) { try { //attempt to deserialize function and execute as closure eval('(' + decodeURI(e.data) + ')();'); } catch(e) {} }
iframe代码:
document.domain = "fiddle.jshell.net";//sync the domains window.addEventListener("message",false);//set up the listener function receiveMessage(e) { //"reply" with a serialized function e.source.postMessage(serializeFunction(doSomething),"http://fiddle.jshell.net"); } function serializeFunction(f) { return encodeURI(f.toString()); } function doSomething() { alert("hello world!"); }
原型模型:parent code和iframe code.