前言
由于同源政策(同源,即同协议、域名、端口)的制定,浏览器限制了跨域请求的访问,而随着前端技术的不断衍变,跨域从最早的JSONP到现在的CORS(跨域资源共享)、到代理、再到WebSocket,前端要实现跨域的技术选择性变得更多,可以实现的功能也更多。
JSONP
讲到跨域实现方式,JSONP肯定是第一个会被提及的。JSONP是JSON with padding的简写,JSONP由两部分组成回调函数和数据,回调函数是前端发送请求时规定的callback的名称,数据则是后端返回给回调函数的数据。
基本格式:
https://www.baidu.com/jsonp/?callback=handlerJsonp
原理:
JSONP的实现原理就是通过创建script标签,设置script标签的src属性,指定为一个带回调函数的请求地址。
主要实现代码:
//定义回调函数
function handlerJsonp(res) {
console.log("后端返回的数据是"+res);
}
//动态创建script标签
var script = document.createElement('script');
script.src = "https://www.abc.com/json/?callback=handlerJsonp";
//插入文档中
document.body.insertBefore(script, document.body.firstChild);
优点:
1. 由于JSONP是最早提出的解决跨域的方案,所以具有很好的兼容性
缺点:
1. JSONP只支持Get请求
2. JSONP的实现是在其他域中加载代码执行,如果其他域存在恶意代码,则会对网站造成很大的危害。
CORS(cross origin resource share)跨域资源共享
CORS跨域资源共享,定义了前端在访问跨域资源时,必须与后端进行沟通,从而确定是否可以进行跨域资源共享。
原理:
跨域资源共享的实现原理则自定义发送HTTP请求的头部,对接上事先规定好的后端规定可以访问的请求源,从而实现请求的响应。
例如:
1. 前端设置请求头:
Origin: http://www.abc.com
2. 后端设置可响应的请求头部对应的源:
Access-Control-Allow-Origin: http://www.abc.com
优点:
1. 可以支持所有的HTTP请求方式
缺点:
1. 不支持旧版本的浏览器
代理
在Vue和React中都提高了代理Proxy的配置方法,通过配置代理可以将请求通过Node.js构建的服务器发送,而服务器和服务器之间是不存在跨域的限制的。
例如(以Vue-Cli2.0为例),在config/index.js中配置:
proxyTable: {
'/api': { // 匹配所有以 '/api'开头的请求路径 即匹配的是axios中传入的url参数,/api/user 这种形式才会匹配
target: 'http://d.apicloud.com/mcm/api', // 代理目标的基础路径
changeOrigin: true, // 支持跨域
pathRewrite: {// 重写路径: 去掉路径中开头的'/api' 当真正的接口不需要api时重写
'^/api': '' //去掉匹配到的路径的/api 如果不去掉就删除pathRewrite
}
}
}
//最后得到的路径就是 target+url
//假设请求的url为 /api/user
//经过node.js代理后 真正请求的是 http://d.apicloud.com/mcm/api/user
//需要注意的是F12显示的仍然是localhost:8080/api/usesr 但实际上发送的地址是经过node.js代理服务器实现的跨域请求
优点:
1. 可以实现通过ajax请求实现跨域请求的成功发送
2. 实现方式简单
缺点:
1. 同样对于旧版本的浏览器来说可能会存在兼容问题,即不支持
WebSocket
浏览器的新兴API有File、requestAnimationFrame、WebSocket等等,其中本次提及的WebSocket可以说是有点厉害!传统的HTTP请求是无状态、无连接的,而WebSocket则旨在实现持久连接、全双工、双向通信,并且WebSocket采用的协议是ws:// 。并且WebSocket非常适合用于移动端的通信,因为不同于HTTP请求,WebSocket每次传递的数据包非常小,很大程度地减小了移动应用的带宽、网络延时所带来的问题。
基本语法:
//实例化一个WebSocket对象
var socket = new WebSocket("ws://www.abc.com/index.jsp")
//发送数据
socket.send('hhhhh');
//接受数据
socket.onmessage = function(event) {
var res = event.data'
}
WebSocket在实例化后,也有和XHR(XMLHttpRequest)类似的readyState属性,其对应的属性值表达的含义如下:
0 正在连接
1 已经建立连接
2 正在关闭连接
3 已经关闭连接
在WebSocket的生命周期的各个阶段,还对应了三个不同的事件,如:
open 成功创建时触发
error 发生错误时触发
close 关闭时触发
优点:
1. 就是前面提及的非常适合用于移动端的开发
缺点:
- 由于WebSocket是新兴的API,在PC端的旧版本浏览器中使用是不支持的
PS:实现跨域方式还有Comet、图形Ping、Hash、postMessage,有需要大家跨域自行去了解哈