跨域产生的原因:浏览器同源策略
浏览器在发送数据请求时,必须满足同源策略才能访问这一资源,同源策略(协议,域名,端口三者必须完全相同),网站资源如果不是在部署的服务器上就会被浏览器拦截,而大多数的情况下,网站资源跟部署的不会在同一个服务器上,这样可以让网站性能提升,对用户友好,要是想访问不是当前部署服务器上的资源,这就需要跨域操作。
解决跨域的几种方式
1. 后端解决
在后端响应头中携带 " Access-Control-Allow-Origin " : " * "
这种方式对于前端开发人员来说是最爽不过的了,在公司你只需要厚着脸皮去和后端开发人员说:兄弟,你在响应头中写那么一句话:" Access-Control-Allow-Origin ":" * ",嘿嘿,你的跨域就解决啦,当然我们在开发的过程当中可能会用到别人的后台数据,那么你也可以和别人公司的后台开发人员说加那么一句话,对方就会和你说一个非常感人的故事:滚!
有时候让后端去操作是很复杂的事,虽然只是一句代码。当然是你这个全栈大佬自己把后端的活也干了那就可以这么做。
2. 前后端一起解决
jsonp 方式解决跨域
jsonp解决跨域完全是搁那卡浏览器的bug,浏览器会对其他发送请求数据的方式进行限制,但是对于不管是我们的script标签的src还是img标签的src,或者说link标签的href他们没有被同源策略所限制。其会向目标地址发送get请求(只支持get请求,不接受追问了,想知道自己去查吧)。所以聪明的程序员就卡bug绕过了浏览器的同源策略去拿到数据,当然了,这种方式也得需要我们的后端配合。
解决方式:
后端会将数据以函数实参的形式放在一个函数中并返回,前端需要定义好这个函数,(其实也可以和后端商量让你自己定义这个函数名的,也不难,就把函数名当成变量而已嘛)不然数据回来之后找不到方法执行,前端只需要在定义好的参数中接收和处理数据即可。
- 前端事先定义好一个同名的回调函数:
<script>
/* JSONP的回调函数 */
function fn(obj) {
/* 处理拿到的数据 */
console.log("data=", obj);
const cities = obj.data.cities;
cities.forEach((item) => console.log(item.name));
/* 删除无用的script标签 */
document.querySelectorAll(".jsonp").forEach(sc=>sc.remove())
}
</script>
- 前端在需要进行跨域数据请求时,创建一个script标签,并将目标地址写入src中:
<script>
btn.onclick = function(e){
/* 动态地创建script标签 */
const sc = document.createElement("script")
// 声明通信地址
sc.src = "http://localhost:8000/files/jsonp/cities"
// 添加一个class以便拿到数据后删除之(卸磨杀驴)
sc.classList.add("jsonp")
// 将script标签丢到页面上并立即执行
document.body.appendChild(sc)
}
</script>
- 后端只需要在收到请求之后返回一个函数,将数据塞到入参即可,还不理解的话就当成后端调用前端的方法,方法调用的时候是不是要传参,你就把数据当成参数传进去就好了。ok,解决!
3. 前端解决
通过代理(正向反向都行)的方式,毕竟求人不如求己。求人家后端,不可能,绝对不可能,那我以后写bug的时候还怎么理直气壮的甩锅给后端!代理的方式是解决跨域最常用的手段,因为它比较霸气(开玩笑的),我们知道浏览器向别人的服务器发送请求会受到同源策略限制,那不简单了嘛,我向自己的服务器发就不会有同源策略的影响啦,但是!!!我们的服务器可没有我们想要的数据,那咋办,嘿,让我们的服务器向别人的服务器发请求拿数据,再转发给我们就好了,同源策略管得了浏览器可管不了我服务器。
代理的方式其实有很多种,我更喜欢 nginx 代理的方式,简单方便。
- 安装nginx(自己琢磨下载安装) : nginx.org/en/download…
- 解压安装包后的文件夹
- 新建一个文件夹(这里我叫dist ,名字任意,也可以用默认的,但一般不用)要记住这个文件名!!!!待会配置的时候会用到!!!!
- 打开conf文件夹
- 找到ndinx.conf 文件,用vscode打开
- 修改默认的根目录 (未修改前是 html ===> dist)dist是前面创建的文件夹名!!!!!!
- 配置代理 可以配置多个
服务的启动和关闭
启动服务:.\nginx.exe -c conf\nginx.con
关闭服务:.\nginx.exe -s stop
并不支持点击 exe 文件打开,所以必须要输入指令,开启之后想重启就必须先关掉,至少我用的时候是这样。