如何实现跨域获取iframe子页面动态的url
有的时候iframe的子页面会动态的切换页面,我们在父页面通过iframe1.contentWindow.window.location只能获取同源的子页面的信息。获取跨域的子页面信息会报错。
这时可以通过html5 提供的接口 postMessage来过去跨域子页面信息。如下代码:
在localhost:8000服务器下的入口测试页面:http://localhost:8000/index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1 id="title"></h1> <h1 id="title_1"></h1> </body> <script> window.addEventListener('message',function(rs){ console.log(rs.data); document.querySelector("#title").innerHTML = rs.data; }); var iframe = document.createElement("iframe"); document.querySelector("body").appendChild(iframe); iframe.setAttribute("src","http://localhost:3000/iframe.html"); //iframe.style.display = "none"; //利用contentWindow.window获取子页面地址 /*setTimeout(function () { document.querySelector("#title_1").innerHTML = iframe.contentWindow.window.location; },1000)*/ </script> </html>
在localhost:3000服务器下的iframe页面:http://localhost:3000/iframe.html
这里页面会自动跳转到iframe_change.html
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <body> <h2>这是iframe里面的内容</h2> </body> <script> window.location.href = "./iframe_change.html"; </script> </html>
在localhost:3000服务器下的iframe_change页面:http://localhost:3000/iframe_change.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h2>iframe already changed</h2> </body> <script> window.parent.postMessage(window.location.href,"*"); </script> </html>
这里调用postMessage发送子页面信息。在index页面通过以下代码来获取子页面信息。
window.addEventListener('message',function(rs){ console.log(rs.data); document.querySelector("#title").innerHTML = rs.data; });
上面的跨域获取iframe动态url的方法可以实现一个微信web开发中一个很重要的问题:
主页面利用https://open.weixin.qq.com/connect/oauth2/authorize获取微信用户信息,主页面的域名是有限制的,需要在公众平台上配置而且一般配置成线上的域名。
但是在实际本地开发的时候,我们主页面的ip一般是localhost或者192.168.1.198:8080,这在微信浏览器上获取用户信息的时候会被拒绝,给开发调试造成极大的不便。
利用上面的iframe的方法就可以绕过域名限制的问题:将获取openId的功能交给单独的一个页面
getOpenId.html负责跳转到微信auth页面授权获取code:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>授权</title> <script> function getUrlParam(name){ var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)", "i"); var r = window.location.search.substr(1).match(reg); if (r != null) return decodeURIComponent(r[2].replace(/%20/g,"+")); return null; } var companyAppId = "wx124345678"; //公司自己的appid var wxCode = getUrlParam('code'); //如果url上没有code,则跳转授权 if(!wxCode){ var url = window.location.href; window.location.href = 'https://open.weixin.qq.com/connect/oauth2/authorize?' + 'appid='+companyAppId+'&redirect_uri='+encodeURIComponent(url)+ '&response_type=code&scope=snsapi_base&state=STATE#wechat_redirect'; }else { //如果url上有code,则说明已经授权完毕可以返回code给主页面 window.parent.postMessage(wxCode,"*"); } </script> </head> <body> </body> </html>
getOpenId.js 在不影响文档流的情况下页面插入iframe进行微信授权,一旦获取到code,则移除iframe。
var wxTool = { getOpenId:function (src,callback) { var iframe = document.createElement("iframe"); iframe.style.display = "none"; document.querySelector("body").appendChild(iframe); iframe.setAttribute("src",src); window.addEventListener('message',function(rs){ console.log(rs.data); callback(rs.data); iframe.remove(); }); } };
index.html
wxTool.getOpenId("http://live.domain.com/getOpenId.html",function (code) { //TODO 利用code请求服务器 获取微信用户信息 })
总结:这种方法也许不是最快的,直接在入口页面的<head>下面写上<script>直接跳转进行微信授权然后重定向回来也许是最快的,但是一旦在跳转授权时由于网络原因可能导致页面会出现短暂的空白,这种情况用户是不愿看到的。而利用iframe的好处是它是异步的,不影响主业务的加载和运行。
所以如果你是希望在初始页面很快的呈现微信用户的信息则用上面第一种方法,否则,使用iframe可能更好些。