跨域操作备忘
什么是同源策略,同源策略最早是由netscape提出的一个网页安全策略。所谓同源是指域名,协议和端口都相同,在这种情况下,开发者可以从其他页面或文件夹相互引用文件和交换数据,因为同属于一个网站,因此不存在安全性的问题。
与同源策略相对是跨域,那么什么情况是跨域。从同源策略的定义我们可以知道,当两个url的域名、协议或者端口,甚至二级域名的某一项或多项不同时,则都属于跨域。
因为从属的网站或子域名不同,因此跨域是不允许交换数据的。虽然我们可以通过一些标签的src属性来引用其他网站的文件,但是无法利用从其他站点得到的数据处理本页面。而本文主要讲述跨域的一些特殊操作。
Iframe
如你所知,我们可以使用Iframe来引用其他页面,或者是一些模块。虽然很方便,但在一般情况下,我们前端是尽量不使用这个元素,因为它会存在很多问题,而且在高性能的javascript中也有提到iframe是文档中最耗系统资源的元素。
但在某些特殊情况下,我们必须采用iframe来引用本站或跨域的文件,因此了解javascript对于iframe的相关操作是很有必要的。
Javascript操作iframe
先说下iframe的一些属性吧!
假设本地服务器有一个页面get_iframe.html,该页面使用iframe引用另一个页面b_iframe.html。
父页面get_iframe要操作b_iframe页面的元素,可以通过iframe的contentWindow属性来获取b_iframe页面的引用,即:
var bIframeEle=iframe.contentWindow.document.getElementById("element"); |
父页面还可以通过以下方法来获取子页面文档的引用,但iframe的此属性不支持低版本的IE浏览器:
var bIframeEle=iframe.contentDocument.getElementById("element"); |
好了,既然父页面可以通过iframe的contentWindow属性来获取子页面元素。那么子页面b_iframe当然也可以通过相关属性来操作父页面get_iframe甚至顶级页面的元素。
获取父页面的元素,可以通过window下的parent属性:
var getIframeEle=window.parent.document.getElementById("element"); |
而获取顶级页面,也就是嵌套iframe最顶层页面的元素,我们则可以使用window下的top属性:
var getIframeEle=window.top.document.getElementById("element"); |
具体的操作方法,可查看此demo:iframe的操作
另外需要说明的是,加载iframe在IE中是需要绑定才可完成。而且以上操作对于chrome浏览器来说,都需要在服务器环境下。
Iframe自适应高(同域)
我们知道,iframe宽高属性在默认情况下是300*150。当我们载入iframe页面时,iframe会出现空白或纵向滚动条。为了页面的美观,我们需要iframe自适应子页面的高度。
同域页面间引用iframe相对来说还是比较简单,我们可以在页面加载完毕后,结合前面提到的属性,去获取iframe所引用页面的高度,然后再动态的设置iframe的高度。
window.onload=function(){ |
需要注意的是,同域引用iframe的src必须是相对路径。可见demo:同域iframe高度自适应
在一些开发中,我们不免涉及跨域引用,因为其他域传递过来的数值不能改变本地元素的属性,所以跨域问题一直令前端开发们非常头疼,那么如何实现跨域引用iframe自适应高呢?
Iframe自适应高(跨域)
iframe跨域高度自适应?如果你的页面只是单纯引入iframe,而没有其他不脱离文档流元素的话,可以考虑下列方案,单纯的css实现,而且页面点击不会跳转url:
<style> |
但如果页面原本有很多内容再引入了iframe,并且还要保持引入的iframe高度自适应,则暂时无法实现。网上提供的代理页面都是扯淡,本人试了很多次都无效。
JSONP
JSON
JSON(JavaScript Object Notation)是一种轻量级的数据交换格式。作为一种数据格式,它与XML相同,可以跨平台传递,这也意味着其他语言也可以使用JSON。但JSON比XML的数据结构简洁,而且可读性好,JSON的值可以是javascript中的任何数据类型
在通常的情况下,JSON都是一些键值对,比如以下这么几种形式:
// 表示一只猫 |
在前面我们创建了几个json,而读取这些Json我们则可以通过for in 循环,如读取cat:
for(var i in cat){ |
若只是读取json中的值,如我们只需要cats中的每个name和age的值,我们则可以这样读取:
for(var i in cats){ |
关于JSON就简单的说这么多,然后接下来看JSONP。
JSONP
前面我们也说过,在跨域情况下,a.com页面中的javascript是无法访问b.com页面里的内容。但src没有跨域限制,我们可以通过src引用其他站点的文件,平常我们在使用其他网站的js文件,比如jquery,我们的做法都是直接引用jquery文件的src,然后在本地服务器页面直接调用jquery定义的方法。
利用这一特性,开发者们就发明了JSONP。JSONP(JSON with Padding)是一种非官方跨域数据交互协议,这种协议是建立在跨域无法获取数据的基础上。第三方网站会提供各种搜索引擎的接口,我们就拿google提供的一个搜索url来分析:
http://ajax.googleapis.com/ajax/services/search/web?v=1.0&q=?&callback=?
因为用户请求的json数据是在远程服务器动态生成的,所以我们采用动态创建script,srcipt的src是像上面说的一个动态地址,其中q的值是用户输入的值,我们可以看到,src中带有一个callback参数,callback的值为一个本地js函数,然后发送这个script请求,当远程服务器响应时,会把生成的json数据“填充”到这个js函数,即作为该方法的参数,最后返回到本地服务器。
简而言之,JSONP可以归纳成这么一个过程:
本地服务器先准备一个方法dataFn(jsonData);
用户操作页面,开始请求远程服务器
然后本地页面根据用户的操作,动态创建script,并且script的src中带有一个callback参数,参数的值为dataFn,即http://www.a.com/web?q=?&callback=dataFn
将script插入文档,开始请求它的src。
远程服务器使用dataFn把它的json数据包括起来作为dataFn的参数,形成一段可运行的js代码,最后返回到本地服务器。
dataFn在本地服务器执行。
具体的jsonp实现可见: jsonp实现搜索。