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 function
function fMain(){
alert(\'main function execute success\');
}
// exec iframe function
function 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 function
function fIframe(){
alert(\'iframe function execute success\');
}
// exec main function
function 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 function
function fMain(){
alert(\'main function execute success\');
}
// exec iframe function
function 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 function
function fIframe(){
alert(\'iframe function execute success\');
}
// exec main function
function 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.js
/** Main 与 Iframe 相互通讯类 支持同域与跨域通讯
* Date: 2013-12-29
* Author: fdipzone
* Ver: 1.0
*/
var FrameMessage = (function(){
this.oFrameMessageExec = null; // 临时iframe
/* 执行方法
executor 执行的页面,为空则为同域
frame 要调用的方法的框架名称,为空则为parent
func 要调用的方法名
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==\'\'){ // parent
parent.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==\'\'){ // parent
return 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\">\'.\"\\r\\n\";
$ret .= $str.\"\\r\\n\";
$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 function
function fMain(profession, skill, company){
var skill_p = JSON.parse(skill);
var company_p = JSON.parse(company);
var msg = \"main function execute success\\n\\n\";
msg += \"profession:\" + profession + \"\\n\";
msg += \"first skill:\" + skill_p.first + \"\\n\";
msg += \"second skill:\" + skill_p.second + \"\\n\";
msg += \"company1:\" + company_p[0] + \"\\n\";
msg += \"company2:\" + company_p[1] + \"\\n\";
alert(msg);
}
// exec iframe function
function exec_iframe(){
// same domain
//FrameMessage.exec(\'\', \'myframe\', \'fIframe\', [\'fdipzone\', \'{\"gender\":\"male\",\"age\":\"29\"}\', \'[\"http://blog.csdn.net/fdipzone\", \"http://weibo.com/fdipzone\"]\']);
// cross domain
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\"]\']);
}
</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 function
function fIframe(name, obj, arr){
var obj_p = JSON.parse(obj);
var arr_p = JSON.parse(arr);
var msg = \"iframe function execute success\\n\\n\";
msg += \"name:\" + name + \"\\n\";
msg += \"gender:\" + obj_p.gender + \"\\n\";
msg += \"age:\" + obj_p.age + \"\\n\";
msg += \"blog:\" + arr_p[0] + \"\\n\";
msg += \"weibo:\" + arr_p[1] + \"\\n\";
alert(msg);
}
// exec main function
function exec_main(){
// same domain
//FrameMessage.exec(\'\', \'\', \'fMain\', [\'programmer\', \'{\"first\":\"PHP\",\"second\":\"javascript\"}\', \'[\"EEG\",\"NMG\"]\']);
// cross domain
FrameMessage.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; ?>
本文地址:https://www.stayed.cn/item/25574
转载请注明出处。
本站部分内容来源于网络,如侵犯到您的权益,请 联系我