jsonp
原理:
JSONP 利用 <script>元素的这个开放策略,网页可以得到从其他来源动态产生的JSON数据,而这种使用模式就是所谓的 JSONP。用JSONP抓到的数据并不是JSON,而是任意的JavaScript,用 JavaScript解释器运行而不是用JSON解析器解析。
<script type="text/javascript">
var localHandler = function(data){
alert('我是本地函数,可以被跨域的remote.js文件调用,远程js带来的数据是:' + data.result); };
</script>
<script type="text/javascript" src="http://remoteserver.com/remote.js"></script>
远程的remote.js
localHandler({"result":"我是远程js带来的数据"});
我本地请求
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<script type="text/javascript">
// 得到航班信息查询结果后的回调函数
var flightHandler = function(data){
alert('你查询的航班结果是:票价 ' + data.price + ' 元,' + '余票 ' + data.tickets + ' 张。');
};
// 提供jsonp服务的url地址(不管是什么类型的地址,最终生成的返回值都是一段javascript代码)
var url = "http://flightQuery.com/jsonp/flightResult.aspx?code=CA1998&callback=flightHandler";
// 创建script标签,设置其属性
var script = document.createElement('script');
script.setAttribute('src', url);
// 把script标签加入head,此时调用开始
document.getElementsByTagName('head')[0].appendChild(script);
</script>
</head>
<body>
</body>
</html>
请求flightResult.aspx获取的数据
flightHandler({
"code": "CA1998",
"price": 1780,
"tickets": 5
});
调用的url中传递了一个code参数,告诉服务器我要查的是CA1998次航班的信息,而callback参数则告诉服务器,我的本地回调函数叫做flightHandler,所以请把查询结果传入这个函数中进行调用。
劣势: 支持get 安全性不高 (可以通过动态生成jsonp解决)
与ajax的区别:
但ajax和jsonp其实本质上是不同的东西。ajax的核心是通过XmlHttpRequest获取非本页内容,而jsonp的核心则是动态添加<script>标签来调用服务器提供的js脚本。
cors
document.domain+iframe(适用于主域名相同的情况)
在域名为http://server.example.com中的a.html
document.domain = 'example.com';
var $iframe = document.createElement('iframe');
$iframe.src = 'server.child.example.com/b.html';
$iframe.style.display = 'none';
document.body.appendChild($iframe);
$iframe.onload = function(){
var doc = $iframe.contentDocument || $iframe.contentWindow.document;
//在这里操作doc,也就是操作b.html
$iframe.onload = null;
};
在域名为http://server.child.example.com中的b.html
document.domain = 'example.com'
这种形式方便归方便,但也有其方便带来的隐患
-
安全性,当一个站点被攻击后,另一个站点会引起安全漏洞。
-
若页面中引入多个iframe,要想操作所有iframe,domain需要全部设置成一样的。
HTML5中的postMessage
postMessage隶属于html5,但是它支持IE8+和其他浏览器,可以实现同域传递,也能实现跨域传递。它包括发送消息postMessage和接收消息message功能。
postMessage调用语法如下
otherWindow.postMessage(message, targetOrigin, [transfer]);
- otherWindow : 其他窗口的一个引用,比如iframe的contentWindow属性、执行window.open返回的窗口对象、或者是命名过或数值索引的window.frames。
- message : 将要发送到其他 window的数据,类型为string或者object。
- targetOrigin : 通过窗口的origin属性来指定哪些窗口能接收到消息事件,其值可以是字符串"*"(表示无限制)或者一个URI。
- transfer (可选) : 一串和message 同时传递的 Transferable 对象。
接收消息message 的属性有:
- data :从其他 window 中传递过来的数据。
- origin :调用 postMessage 时消息发送方窗口的 origin 。
- source :对发送消息的窗口对象的引用。
示例如下:域名http://127.0.0.1:9000页面A通过iframe嵌入了http://127.0.0.1页面B,接下来页面A将通过postMessage对页面B进行数据传递,页面B将通过message属性接收页面A的数据
页面A发送消息代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>页面A</title>
</head>
<body>
<h1>hello jsonp</h1>
<iframe src="http://127.0.0.1/b.html" id="iframe"></iframe>
</body>
</html>
<script>
window.onload = function() {
var $iframe = document.getElementById('iframe');
var targetOrigin = "http://127.0.0.1";
$iframe.contentWindow.postMessage('postMessage发送消息', targetOrigin);
};
</script>
页面B接收消息代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>页面B</title>
</head>
<body>
<h1>hello jsonp</h1>
</body>
</html>
<script>
var onmessage = function (event) {
var data = event.data; //消息
var origin = event.origin; //消息来源地址
var source = event.source; //源Window对象
if(origin === "http://127.0.0.1:9000"){
console.log(data, origin, source);
}
};
// 事件兼容简单处理
if (window.addEventListener) {
window.addEventListener('message', onmessage, false);
}
else if (window.attachEvent) {
window.attachEvent('onmessage', onmessage);
}
else {
window.onmessage = onmessage;
}
</script>
运行结果如下
![](https://img.haomeiwen.com/i1889471/cc3206c55ddbfdcf.png)
网友评论