知识点:
- 什么是同源策略及限制
- 前后端如何通信
- 如何创建 ajax
- 跨域通信的几种方式
1. 什么是同源策略及限制
同源策略:限制从一个源加载的文档或脚本如何与另一个源的资源进行交互。这是一个用于隔离潜在恶意文件的关键的安全机制。
限制:
- Cookie、LocalStorage 和 IndexDB 无法读取
- DOM 无法获得
- AJAX 请求不能发送
2. 前后端如何通信
- ajax:同源策略
- WebSocket:不受同源限制
- CORS:都支持
3. 何创建 ajax
- XMLHttpRequest 对象的工作流程
- 兼容性处理
- 事件的触发条件
- 事件的触发顺序
//AjAX的请求封装
function ajax(method,url,params,done){
//统一转换为大写便于后续判断
method =method.toUpperCase();
//对象形式的参数转换为urlencoded格式
var pairs=[];
for(var key in params){
paies.push(key+'='+params[key])
}
var querystring=pairs.join('&');
var xhr=window.XMLHttpRequest ? new XMLHttpRequest():new ActiveXObject('Microsoft.XMLHTTP');
xhr.addEventListener('readystatechange',function(){
if(this.readyState!==4) return;
//尝试通过JSON格式解析响应体
try{
done(JSON.parse(this.responseText))
}catch(e){
done(this.responseText)
}
})
//如果是GET请求就设置URL地址问号参数
if(method==='GET'){
url+='?'+querystring;
}
xhr.open(method,url);
//如果是POST请求就设置请求体
var data=null;
if(method==='POST'){
xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded')
data=querystring;
}
xhr.send(data);
}
ajax('get','./get.php',{id:123},function(data){
console.log(data)
})
ajax('post','./post.php',{foo:'posted data'},function(data){
console.log(data);
})
4. 跨域通信的几种方式
- JSONP
- Hash
- postMessage
- WebSocket
- CORS
4.1 JSONP
script 跨域请求跨域链接时,会返回 callback
<script>
window.callback = function (data) {
console.log(data); //这是我们得到的跨域信息
}
</script>
<script src="http://coding.m.imooc.com/api.js"></script>
function jsonp (url, params, callback) {
var funcName = 'jsonp_' + Date.now() + Math.random().toString().substr(2, 5)
if (typeof params === 'object') {
var tempArr = []
for (var key in params) {
var value = params[key]
tempArr.push(key + '=' + value)
}
params = tempArr.join('&')
}
var script = document.createElement('script')
script.src = url + '?' + params + '&callback=' + funcName
document.body.appendChild(script)
window[funcName] = function (data) {
callback(data)
delete window[funcName]
document.body.removeChild(script)
}
}
jsonp('http://localhost/jsonp/server.php', { id: 123 }, function (res) {
console.log(res)
4.2 Hash
Hash:是url地址中#后面的部分,Hash改变页面不刷新。
Search:是url地址中?后的部分,改变页面会刷新.
// 利用hash,场景是当前页面 A 通过iframe或frame嵌入了跨域的页面 B
// 在A中伪代码如下:
var B = document.getElementsByTagName('iframe');
B.src = B.src + '#' + 'data';
// 在B中的伪代码如下
window.onhashchange = function () {
var data = window.location.hash;
};
4.3 postMessage
// postMessage
// 窗口A(http:A.com)向跨域的窗口B(http:B.com)发送信息
Bwindow.postMessage('data', 'http://B.com');
// 在窗口B中监听
Awindow.addEventListener('message', function (event) {
console.log(event.origin);
console.log(event.source);
console.log(event.data);
}, false);
4.4 WebSocket
WebSocket,即浏览器与web服务器之间全双工通信标准。一旦web服务器与客户端建立了WebSocket协议的通信连接,之后所有的通信都依靠这个专用协议执行。通信过程中,可互相发送JSON、XML、HTML或图片等任意格式的数据。
主要特点:
- 推送功能。支持由服务器向客户端推送数据的推送功能。这样服务器可直接发送数据,而不必等待客户端的请求;
- 减少通信量。只要建立起WebSocket连接,就希望一直保持连接状态。和HTTP相比,不但每次连接时的总开销减少,而且由于WebSocket的首部信息很小,通信量也相应减小了。
// Websocket【参考资料】http://www.ruanyifeng.com/blog/2017/05/websocket.html
var ws = new WebSocket('wss://echo.websocket.org');
ws.onopen = function (evt) {
console.log('Connection open ...');
ws.send('Hello WebSockets!');
};
ws.onmessage = function (evt) {
console.log('Received Message: ', evt.data);
ws.close();
};
ws.onclose = function (evt) {
console.log('Connection closed.');
}
5. CORS
fetch就是用来实现CORS通信的
// CORS【参考资料】http://www.ruanyifeng.com/blog/2016/04/cors.html
// url(必选),options(可选)
fetch('/some/url/', {
method: 'get',
}).then(function (response) {
}).catch(function (err) {
// 出错了,等价于 then 的第二个参数,但这样更好用更直观
});
CORS为什么能支持跨域通信:如果请求是跨域的,浏览器会拦截AJAX请求,它会在HTTP头部中加Origin。