iframe 与主框架相互访问方法1.同域相互访问假设A.html 与 b.html domain都是localhost (同域)
A.html中iframe 嵌入 B.html,name=myframe
A.html有js function fMain()
B.html有js function fIframe()
需要实现 A.html 调用 B.html 的 fIframe(),B.html 调用 A.html 的 fMain()
A.html
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"><title> main window </title> <script type="text/javascript">// main js functionfunction fMain(){alert("main function execute success");} // exec iframe functionfunction exec_iframe(){window.myframe.fIframe();}</script> </head> <body><p>A.html main</p><p><input type="button" value="exec iframe function" onclick="exec_iframe()"></p><iframe src="B.html" name="myframe" width="500" height="100"></iframe></body> </html> B.html
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"><title> iframe window </title> <script type="text/javascript">// iframe js functionfunction fIframe(){alert("iframe function execute success");} // exec main functionfunction exec_main(){parent.fMain();}</script> </head> <body><p>B.html iframe</p><p><input type="button" value="exec main function" onclick="exec_main()"></p></body> </html> 点击A.html 的 exec iframe function button,执行成功,弹出iframe function execute success。如下图

点击B.html 的 exec main function button,执行成功,弹出 main function execute success。如下图
2.跨域互相访问假设 A.html domain是 localhost, B.html domain 是 127.0.0.1 (跨域)
这里使用 localhost 与 127.0.0.1 只是方便测试,localhost 与 127.0.0.1已经不同一个域,因此执行效果是一样的。
实际使用时换成 www.domaina.com 与 www.domainb.com 即可。
A.html中iframe 嵌入 B.html,name=myframe
A.html有js function fMain()
B.html有js function fIframe()
需要实现 A.html 调用 B.html 的 fIframe(),B.html 调用 A.html 的 fMain() (跨域调用)
如果使用上面同域的方法,浏览器判断A.html 与 B.html 不同域,会有错误提示。
Uncaught SecurityError: Blocked a frame with origin "http://localhost" from accessing a frame with origin "http://127.0.0.1". Protocols, domains, and ports must match.
实现原理:
因为浏览器为了安全,禁止了不同域访问。因此只要调用与执行的双方是同域则可以相互访问。
首先,A.html 如何调用B.html的 fIframe方法
1.在A.html 创建一个 iframe
2.iframe的页面放在 B.html 同域下,命名为execB.html
3.execB.html 里有调用B.html fIframe方法的js调用
<script type="text/javascript"> parent.window.myframe.fIframe(); // execute parent myframe fIframe function </script>
这样A.html 就能通过 execB.html 调用 B.html 的 fIframe 方法了。
同理,B.html 需要调用A.html fMain方法,需要在B.html 嵌入与A.html 同域的 execA.html
execA.html 里有调用 A.html fMain 方法的js 调用
<script type="text/javascript"> parent.parent.fMain(); // execute main function </script>
这样就能实现 A.html 与 B.html 跨域相互调用。
A.html
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"><title> main window </title> <script type="text/javascript"> // main js functionfunction fMain(){alert("main function execute success");} // exec iframe functionfunction exec_iframe(){if(typeof(exec_obj)=="undefined"){ exec_obj = document.createElement("iframe"); exec_obj.name = "tmp_frame"; exec_obj.src = "http://127.0.0.1/execB.html"; exec_obj.style.display = "none"; document.body.appendChild(exec_obj);}else{ exec_obj.src = "http://127.0.0.1/execB.html?" + Math.random();}}</script> </head> <body><p>A.html main</p><p><input type="button" value="exec iframe function" onclick="exec_iframe()"></p><iframe src="http://127.0.0.1/B.html" name="myframe" width="500" height="100"></iframe></body> </html> B.html
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"><title> iframe window </title> <script type="text/javascript">// iframe js functionfunction fIframe(){alert("iframe function execute success");} // exec main functionfunction exec_main(){if(typeof(exec_obj)=="undefined"){ exec_obj = document.createElement("iframe"); exec_obj.name = "tmp_frame"; exec_obj.src = "http://localhost/execA.html"; exec_obj.style.display = "none"; document.body.appendChild(exec_obj);}else{ exec_obj.src = "http://localhost/execA.html?" + Math.random();}}</script> </head> <body><p>B.html iframe</p><p><input type="button" value="exec main function" onclick="exec_main()"></p></body> </html> execA.html
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"><title> exec main function </title></head> <body><script type="text/javascript"> parent.parent.fMain(); // execute main function</script></body> </html>
execB.html
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"><title> exec iframe function </title></head> <body><script type="text/javascript"> parent.window.myframe.fIframe(); // execute parent myframe fIframe function</script></body> </html>
执行如下图:
php main 与 iframe 相互通讯类(同域/跨域)
把main与iframe相互通讯的方法封装成类,主要有两个文件,
JS:FrameMessage.js 实现调用方法的接口,如跨域则创建临时iframe,调用同域执行者。
PHP:FrameMessage.class.php 实现接收到跨域请求时,根据参数返回执行方法的JS code。
功能如下:
1.支持同域与跨域通讯
2.传递的方法参数支持字符串,JSON,数组等。
复制代码 代码如下:FrameMessage.exec("http://127.0.0.1/execB.php", "myframe", "fIframe", ["fdipzone", "{"gender":"male","age":"29"}", "["http://blog.csdn.net/fdipzone", "http://weibo.com/fdipzone"]"]);
复制代码 代码如下:FrameMessage.exec("http://localhost/execA.php", "", "fMain", ["programmer", "{"first":"PHP","second":"javascript"}", "["EEG","NMG"]"]);
FrameMessage.js
/** Main 与 Iframe 相互通讯类 支持同域与跨域通讯 * Date: 2013-12-29 * Author: fdipzone * Ver: 1.0 */ var FrameMessage = (function(){ this.oFrameMessageExec = null; // 临时iframe /* 执行方法executor 执行的页面,为空则为同域frame 要调用的方法的框架名称,为空则为parentfunc要调用的方法名args要调用的方法的参数,必须为数组[arg1, arg2, arg3, argn...],方便apply调用 元素为字符串格式,请不要使用html,考虑注入安全的问题会过滤*/this.exec = function(executor, frame, func, args){this.executor = typeof(executor)!="undefined"? executor : ""; this.frame = typeof(frame)!="undefined"? frame : ""; this.func = typeof(func)!="undefined"? func : ""; this.args = typeof(args)!="undefined"? (__fIsArray(args)? args : []) : []; // 必须是数组if(executor==""){__fSameDomainExec(); // same domain }else{__fCrossDomainExec(); // cross domain } } /* 同域执行 */function __fSameDomainExec(){ if(this.frame==""){ // parentparent.window[this.func].apply(this, this.args); }else{window.frames[this.frame][this.func].apply(this, this.args); }} /* 跨域执行 */function __fCrossDomainExec(){ if(this.oFrameMessageExec == null){this.oFrameMessageExec = document.createElement("iframe");this.oFrameMessageExec.name = "FrameMessage_tmp_frame";this.oFrameMessageExec.src = __fGetSrc();this.oFrameMessageExec.style.display = "none";document.body.appendChild(this.oFrameMessageExec); }else{this.oFrameMessageExec.src = __fGetSrc(); }} /* 获取执行的url */function __fGetSrc(){ return this.executor + (this.executor.indexOf("?")==-1? "?" : "&") + "frame=" + this.frame + "&func=" + this.func + "&args=" + JSON.stringify(this.args) + "&framemessage_rand=" + Math.random();} /* 判断是否数组 */function __fIsArray(obj){ return Object.prototype.toString.call(obj) === "[object Array]";} return this;}()); FrameMessage.class.php
<?php /** Frame Message class main 与 iframe 相互通讯类 * Date: 2013-12-29 * Author: fdipzone * Ver: 1.0 * * Func: * public execute 根据参数调用方法 * private returnJs 创建返回的javascript * private jsFormat 转义参数 */class FrameMessage{ // class start /* execute 根据参数调用方法* @param String $frame 要调用的方法的框架名称,为空则为parent* @param String $func 要调用的方法名* @param JSONstr $args 要调用的方法的参数* @return String*/public static function execute($frame, $func, $args=""){if(!is_string($frame) || !is_string($func) || !is_string($args)){return ""; }// frame 与 func 限制只能是字母数字下划线 if(($frame!="" && !preg_match("/^[A-Za-z0-9_]+$/",$frame)) || !preg_match("/^[A-Za-z0-9_]+$/",$func)){return ""; }$params_str = "";if($args){$params = json_decode($args, true);if(is_array($params)){for($i=0,$len=count($params); $i<$len; $i++){ // 过滤参数,防止注入$params[$i] = self::jsFormat($params[$i]); }$params_str = """.implode("","", $params).""";} }if($frame==""){ // parentreturn self::returnJs("parent.parent.".$func."(".$params_str.");"); }else{return self::returnJs("parent.window.".$frame.".".$func."(".$params_str.");"); } }/** 创建返回的javascript* @param String $str* @return String*/private static function returnJs($str){$ret = "<script type="text/javascript">"."
"; $ret .= $str."
"; $ret .= "</script>";return $ret;}/** 转义参数* @param String $str* @return String*/private static function jsFormat($str){$str = strip_tags(trim($str)); // 过滤html $str = str_replace("\s\s", "\s", $str); $str = str_replace(chr(10), "", $str); $str = str_replace(chr(13), "", $str); $str = str_replace(" ", "", $str); $str = str_replace("\", "\\", $str); $str = str_replace(""", "\"", $str); $str = str_replace("\"", "\\"", $str); $str = str_replace(""", """, $str);return $str;}} // class end?> A.html
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"><title> main window </title><script type="text/javascript" src="json2.js"></script><script type="text/javascript" src="FrameMessage.js"></script> <script type="text/javascript"> // main js functionfunction fMain(profession, skill, company){ var skill_p = JSON.parse(skill);var company_p = JSON.parse(company);var msg = "main function execute success
";msg += "profession:" + profession + "
";msg += "first skill:" + skill_p.first + "
";msg += "second skill:" + skill_p.second + "
";msg += "company1:" + company_p[0] + "
";msg += "company2:" + company_p[1] + "
"; alert(msg); } // exec iframe functionfunction exec_iframe(){// same domain//FrameMessage.exec("", "myframe", "fIframe", ["fdipzone", "{"gender":"male","age":"29"}", "["http://blog.csdn.net/fdipzone", "http://weibo.com/fdipzone"]"]); // cross domainFrameMessage.exec("http://127.0.0.1/execB.php", "myframe", "fIframe", ["fdipzone", "{"gender":"male","age":"29"}", "["http://blog.csdn.net/fdipzone", "http://weibo.com/fdipzone"]"]);}</script> </head> <body><p>A.html main</p><p><input type="button" value="exec iframe function" onclick="exec_iframe()"></p><!-- same domain --><!--<iframe src="B.html" name="myframe" width="500" height="100"></iframe>--><!-- cross domain --><iframe src="http://127.0.0.1/B.html" name="myframe" width="500" height="100"></iframe></body> </html> B.html<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"><title> iframe window </title><script type="text/javascript" src="json2.js"></script><script type="text/javascript" src="FrameMessage.js"></script> <script type="text/javascript"> // iframe js functionfunction fIframe(name, obj, arr){var obj_p = JSON.parse(obj);var arr_p = JSON.parse(arr);var msg = "iframe function execute success
";msg += "name:" + name + "
";msg += "gender:" + obj_p.gender + "
";msg += "age:" + obj_p.age + "
";msg += "blog:" + arr_p[0] + "
";msg += "weibo:" + arr_p[1] + "
"; alert(msg); } // exec main functionfunction exec_main(){// same domain//FrameMessage.exec("", "", "fMain", ["programmer", "{"first":"PHP","second":"javascript"}", "["EEG","NMG"]"]); // cross domainFrameMessage.exec("http://localhost/execA.php", "", "fMain", ["programmer", "{"first":"PHP","second":"javascript"}", "["EEG","NMG"]"]);}</script> </head> <body><p>B.html iframe</p><p><input type="button" value="exec main function" onclick="exec_main()"></p></body> </html> execA.php 与 execB.php
<?php require "FrameMessage.class.php";$frame = isset($_GET["frame"])? $_GET["frame"] : ""; $func = isset($_GET["func"])? $_GET["func"] : ""; $args = isset($_GET["args"])? $_GET["args"] : "";$result = FrameMessage::execute($frame, $func, $args);echo $result; ?>