一,原理:
iframe在加载新页面时,name值是保持不变的,由此可以重定向iframe的引用地址,由外域转到本域。
二,方法:
设置请求目标域页面的window.name,通过iframe引用至本域,由于js受到浏览器同源策略限制,无法跨域通信,取不到iframe中传过来 的window.name设置值,所以需要在本域设置一个代理页面(空文件即可),监听iframe的load事件,一旦加载完成,设置iframe指向 本域下的代理页面,此时就不存在跨域问题了,同时js可以取得iframe传输过来的跨域数据,即window.name值。
以下是封装的组件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
| * 构造函数(利用window.name跨域访问,保证目标页面设置window.name) * @class windowName */ var windowName = function(){ this.init.apply(this,arguments); }; windowName.prototype = { * 初始化 * @param url{string} 目标域url地址 * @param config{object} 配置项 * @配置说明:proxy{string} 本域下的代理页面地址 * callback(function) 处理数据的回调 * @return void */ init: function(url,config){ var that = this; that.status = false; that.data = ''; var config = that.checkInterface(config); that.getData(url,config); }, * 验证接口,构建正确的参数形式 * @param obj{object} 配置项 * @return object */ checkInterface: function(obj){ return { proxy: obj.proxy || 'proxy.html', callback: obj.callback || new Function }; }, * 对iframe的onload实现事件监听 * @param frame{dom} 对象 * @param callback(function) 回调 * @return void */ frameLoad: function(frame,callback){ if(frame.attachEvent){ frame.attachEvent('onload',function(){ callback(); }); }else{ frame.onload = function(){ callback(); } } }, * 获取跨域数据,并执行回调 * @param url{string} 目标域url地址 * @param config{object} 配置项 * @配置说明:proxy{string} 本域下的代理页面地址 * callback(function) 处理数据的回调 * @return void */ getData: function(url,config){ var that = this; var frame = that.frame = document.createElement('iframe'); frame.style.visibility = 'hidden'; frame.style.height = '0'; document.body.insertBefore(frame,null); that.frameLoad(frame,function(){ if(that.status){ that.data = frame.contentWindow.name; that.clearFrame(); config.callback(that.data); }else{ that.status = true; frame.contentWindow.location.href = config.proxy; } }); frame.src = url; }, * 清除iframe * @param */ clearFrame: function(){ var that = this; that.frame.parentNode.removeChild(that.frame); } };
|
使用方法:
1 2 3 4 5 6 7 8 9 10 11
| var btn = document.getElementById('btn'), var result = document.getElementById('result'); btn.onclick = function(){ new windowName('http://third-party-sources.com',{ //本域下的代理页面(空页面即可) proxy: 'test.html', callback: function(o){ result.innerHTML = o; } }); };
|
更多关于跨域的知识,请猛击:这里
update in 2011-08-30 by zhenn:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| windowName.prototype.getData = function(){ var that = this; var frame = that.frame = document.createElement('iframe'); * 用visibility代替display * 避免使用此方法做跨域iframe高度自适应时的bug * 当iframe设置display:none * 设置目标页面window.name = document.body.offsetHeight -> window.name = 0 */ frame.style.visibility = 'hidden'; frame.style.height = '0'; document.body.insertBefore(frame,null); that.frameLoad(frame,function(){ if(that.status){ that.data = frame.contentWindow.name; that.clearFrame(); config.callback(that.data); }else{ that.status = true; frame.contentWindow.location.href = config.proxy; } }); frame.src = url; };
|