以下皆个人理解,有错请指出,谢谢。
什么是跨域
跨域是指浏览器的同源策略产生的现象,因为浏览器可以同时打开多个标签页,如果不将这些网页加以分隔,那么将出现a网站去访问b网站,还能带上b网站的cookie,且能收到b网站的响应。使得a网站很容易窃取用户在b网站上的数据。于是便有了浏览器的同源策略。
同源策略是指当http请求时,如果客户端与服务端的协议、主机、端口号,任意一个不相同的时候,客户端(浏览器)会在发出请求的时候,会自动在请求头上加上Origin字段,说明请求来自哪个源,如果接收到的响应体里没有Access-Control-Allow-Origin字段或这个字段中没有自己发出去时带上的源,(也就是服务端带过来的Access-Control-Allow-Origin中没有自己发过去的地址)则会拦截下服务端的响应并且丢弃。这就称之为同源策略,或者说,此时产生了跨域。
解决方案
后端设置响应头
让后端来解决。后端在请求头上加上Access-Control-Allow-Origin,并且指定哪个请求加入这个其中,如果是*则是任意请求允许跨域。
JSONP
原理是使用script标签,这个都知道,问题是怎么写。
首先script只能发送get请求,这就意味着要么不传参,要么传参只能传字符串参数。
先定义一个函数。JSONP=({url,params,callback})=>{}
这个JSONP最后是要返回一个Promise对象,且是resolve过了的。直接.then 里面的res就是后端的返回的结果
其次内部怎么写呢?先拼接url,url+=`?{callback}`
url里有参数,我们就再把参数拼接上url
let keys = Object.keys(params)
for(let i=0;i< keys.length;i++){url+=`&${keys[i]}=${params[keys[i]] }`}
全部拼接完成之后createElement(‘script’)然后将其src=url
再document.appendChild加入到文档中。重点来了,在一个Promise中声明这个callback函数,因为是window[callbackName]所以是将这个函数声明挂在到了全局window下
这里可没有执行哦。只是声明。当我们增加的那个script标签请求完成了,会回来执行这个callbackName()函数。而我们这不刚好声明了嘛,一执行,一resolve,那个Promise实例就成功了。res就是那个数据啦。
只能说确实巧妙。最后还不忘删除这个无用的script标签。
附上代码作者为:zy懒人漫游的代码
出处:https://www.jianshu.com/p/f9143a034b13
jsonp('http://photo.sina.cn/aj/index', {
page: 1,
cate: 'recommend'
}, 'jsoncallback').then(res => {
console.log(res.data);
}).catch(err=>{
console.log(err);
})
function jsonp(url,data,callback){
return new Promise((resolve)=>{
var script = document.createElement('script')
url += `?jsoncallback=${callback}`
if(data){
Object.keys(data).forEach(key=>{
url += `&${key}=${data[key]}`
})
}
script.src = url
document.head.appendChild(script)
window[callback] = function (data){
resolve(data)
}
script.parentNode.removeChild(script)
})
}
使用Vue.config.js的代理服务器
因为跨域只存在浏览器与服务器之间,而服务器和服务器之间是没有跨域问题的
在Vue.config.js中加上这三行,代表使用代理服务器。发请求可以直接往本地发(axios的url填本地8080就行,看你是啥就是啥),代理服务器会帮你转发到真正的服务器
devServer: {
proxy: 'http://luoying.free.idcfengye.com'
}
参考文章