1. JSONP
JSONP是服务器与客户端跨源通信的常用方法。最大特点就是简单适用,老式浏览器全部支持,服务器改造非常小。
它的基本思想是,网页通过添加一个元素,向服务器请求JSON数据,这种做法不受同源政策限制;服务器收到请求后,将数据放在一个指定名字的回调函数里传回来。
Example
使用如下接口 https://api.asilu.com/ip/
// 输出
{
"ip": "118.250.83.107",
"dz": "湖南省长沙市",
"wl": "电信"
}
mock测试
// 后端mock
router.get('/test',function(req,res){
var cb = req.query.callback
var mockData = {
a1:'abc',
a2:'123',
a3:'hello'
}
res.send(cb + '(' + JSON.stringify(mockData) +')')
})
// 输出
Object {a1: "abc", a2: "123", a3: "hello"}
script封装写法
function addScriptTag(src) {
var script = document.createElement('script');
script.setAttribute("type","text/javascript");
script.src = src;
document.body.appendChild(script);
}
window.onload = function () {
addScriptTag('http://example.com/ip?callback=foo');
}
function foo(data) {
console.log('Your public IP address is: ' + data.ip);
};
2. CORS
CORS需要浏览器和服务器同时支持。目前,所有浏览器都支持该功能,IE浏览器不能低于IE10。
整个CORS通信过程,都是浏览器自动完成,不需要用户参与。对于开发者来说,CORS通信与同源的AJAX通信没有差别,代码完全一样。浏览器一旦发现AJAX请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感觉。
因此,实现CORS通信的关键是服务器。只要服务器实现了CORS接口,就可以跨源通信。
Example
使用如下接口 http://api.jirengu.com/city.php
// 输出
长沙市
mock测试
// 后端
router.get('/test2',function(req,res){
var cb = req.query.callback
var mockData = {
a1:'abc',
a2:'123',
a3:'hello'
}
console.log(res.header)
res.header('Access-Control-Allow-Origin','*')
res.send(mockData)
})
// 输出
Object {a1: "abc", a2: "123", a3: "hello"}
3. postMessage
HTML5引入了一个全新的API:跨文档通信 API(Cross-document messaging)。
这个API为window对象新增了一个window.postMessage
方法,允许跨窗口通信,不论这两个窗口是否同源。
举例来说,父窗口aaa.com向子窗口bbb.com发消息,调用postMessage
方法就可以了。
Example
// 父窗口代码
// 子窗口代码
4. 片段识别符
片段标识符(fragment identifier)指的是,URL的#
号后面的部分,比如http://example.com/x.html#fragment
的#fragment
。如果只是改变片段标识符,页面不会重新刷新。
父窗口可以把信息,写入子窗口的片段标识符。
var src = originURL + '#' + data;
document.getElementById('myIFrame').src = src;
子窗口通过监听hashchange事件得到通知。
window.onhashchange = checkMessage;
function checkMessage() {
var message = window.location.hash;
// ...
}r
同样的,子窗口也可以改变父窗口的片段标识符。
parent.location.href= target + “#” + hash;
example
// 父页面
// 子页面
两个页面不在同一个域下IE、Chrome不允许修改parent.location.hash的值
参考
阮一峰 - 同源政策
林东洲 - 关于跨域