前言:
在前端發(fā)出Ajax請求的時(shí)候,有時(shí)候會(huì)產(chǎn)生跨域問題,報(bào)錯(cuò)如下:
Access to XMLHttpRequest at ‘http://127.0.0.1/api/post’ from origin ‘null’ has been blocked by CORS policy: No ‘Access-Control-Allow-Origin’ header is present on the requested resource.
針對以上問題,本文提供兩種解決方案,CORS中間件和JSONP方法。
在具體介紹解決方法之前,我們先明確以下前提條件:
1、這兩個(gè)方法都需要通過后端修改接口情況,無法單獨(dú)通過前端解決跨域問題。
2、什么是跨域?什么情況會(huì)出現(xiàn)跨域?
答:當(dāng)瀏覽器發(fā)起Ajax請求時(shí),如果所請求的url和當(dāng)前的url的協(xié)議、域名、端口存在任意不同,就會(huì)產(chǎn)生跨域問題。比如我在這個(gè)地址file:///C:/Users/%E8%8A%.html,協(xié)議為file協(xié)議,如果請求http協(xié)議的文件,自然就會(huì)出現(xiàn)跨域問題。
3、當(dāng)我們使用script、img、herf加載內(nèi)容時(shí)不會(huì)出現(xiàn)跨域問題
好,接來下我們先給出出現(xiàn)問題的前 后端代碼,看看這個(gè)時(shí)候?qū)?yīng)前后端都做了什么事:
首先是前端:使用ajax發(fā)送get請求,請求地址為http://127.0.0.1/api/get,由于前端頁面使用file格式打開,所以在請求http協(xié)議的本機(jī)地址是會(huì)產(chǎn)生跨域問題。
$(“#btnGET”).on(“click”, function () {
$.ajax({
type: “GET”,
url: “http://127.0.0.1/api/get”,
success: function (res) {
console.log(res);
},
});
});
然后是后端:當(dāng)請求的路由地址為/api/get的時(shí)候,返回對應(yīng)的內(nèi)容和query屬性
app.get(‘/api/get’,(req, res) => {
// 通過 req.query 獲取客戶端通過查詢字符串,發(fā)送到服務(wù)器的數(shù)據(jù)
const query = req.query;
// 調(diào)用 res.send() 方法,向客戶端響應(yīng)處理的結(jié)果
res.send({
status: 0, // 0 表示處理成功,1 表示處理失敗
msg: “GET 請求成功!”, // 狀態(tài)的描述
data: query, // 需要響應(yīng)給客戶端的數(shù)據(jù)
});
})
OK,說完發(fā)生跨域問題的情況,我們接下來講解決方法:
方法一:引入cors中間件
這個(gè)方法很簡單只要在后端加入兩行代碼。(首先要先npm install cors 安裝包),修改后的后端代碼如下
const cors = require(“cors”);
app.use(cors()); //使用cors中間件
app.get(‘/api/get’,(req, res) => {
// 通過 req.query 獲取客戶端通過查詢字符串,發(fā)送到服務(wù)器的數(shù)據(jù)
const query = req.query;
// 調(diào)用 res.send() 方法,向客戶端響應(yīng)處理的結(jié)果
res.send({
status: 0, // 0 表示處理成功,1 表示處理失敗
msg: “GET 請求成功!”, // 狀態(tài)的描述
data: query, // 需要響應(yīng)給客戶端的數(shù)據(jù)
});
})
可以看到,引入了cors中間件之后,跨域問題可以得到解決,那么為什么解決,這么解決的原理是什么呢?讓我們回到前面的報(bào)錯(cuò)內(nèi)容:
No ‘Access-Control-Allow-Origin’ header is present on the requested resource.意思就是說,所請求的資源沒有Access-Control-Allow-Origin這個(gè)頭,好的。那我們就把這個(gè)頭給他安上,發(fā)現(xiàn)問題也可以解決,那么cors中間件是不是就是使用的這種方法呢?
app.get(‘/api/get’,(req, res) => {
// 通過 req.query 獲取客戶端通過查詢字符串,發(fā)送到服務(wù)器的數(shù)據(jù)
res.header(“Access-Control-Allow-Origin”, “*”); 設(shè)置響應(yīng)頭,*表示任何地址都亦可以訪問
const query = req.query;
// 調(diào)用 res.send() 方法,向客戶端響應(yīng)處理的結(jié)果
res.send({
status: 0, // 0 表示處理成功,1 表示處理失敗
msg: “GET 請求成功!”, // 狀態(tài)的描述
data: query, // 需要響應(yīng)給客戶端的數(shù)據(jù)
});
})
我們發(fā)現(xiàn)當(dāng)我們使用了cors中間件之后,使用瀏覽器抓包,可以看到相應(yīng)頭里確實(shí)有了這個(gè)字段
所以綜上所述,cors中間件就是幫我們自動(dòng)設(shè)置了響應(yīng)頭,從而解決跨域問題。
方法二:JSONP
簡單來說,JSONP就是通過前端的script腳本從后端請求回來一段js代碼并且執(zhí)行從而獲得數(shù)據(jù),前端代碼如下(視頻截圖下來的。。我懶得打字了)。。然后圈個(gè)重點(diǎn)JSONP只支持GET請求
來,我們解釋一下:首先通過第一個(gè)script腳本注冊一個(gè)函數(shù)f,那么這個(gè)函數(shù)自然就存在了,后面使用的腳本也能用f這個(gè)函數(shù),這個(gè)道理和你用script引入一個(gè)jquery然后后面用 $ 開始一通操作是一樣的道理。然后第二個(gè)script腳本訪問一個(gè)跨域的資源,然后我們傳入?yún)?shù)callback=f,這個(gè)參數(shù)有什么用呢?答:后端需要獲取這個(gè)callback參數(shù)里面的值,然后把這個(gè)值(也就是f)拼接成一個(gè)函數(shù)然后返回回來給前端執(zhí)行,對應(yīng)后端代碼如圖。
前端代碼:
后端代碼:可以看到這個(gè)funcname對應(yīng)的就是那個(gè)f,然后拼接一下就變成了f(‘你好’),那么這個(gè)東西就返回給了前端。但是但是前端這個(gè)時(shí)候注冊了一個(gè)f函數(shù)呀,所以就會(huì)執(zhí)行這個(gè)f(‘你好’),那么前端的數(shù)據(jù)也就請求回來了。
到這里,兩種方法都講完了,下面補(bǔ)充一種讓我懵逼了很久的jquery的jsonp解決方法
直接上代碼:(后端代碼不變,還是拼接一個(gè)函數(shù)回來執(zhí)行)
$(“#btnJSONP”).on(“click”, function () {
$.ajax({
type: “GET”,
url: “http://127.0.0.1/api/jsonp”,
dataType: “jsonp”,
jsonp: “callback”,
jsonpCallback: “f”,
success: function (res) {
console.log(res);
},
});
});
打開控制臺(tái),可以看到j(luò)query發(fā)送的這個(gè)請求其實(shí)和剛才是差不多的
同樣是拼接了一個(gè)callback參數(shù)給后端,后端返回js代碼,此外呢,上面這段代碼的jsonp參數(shù)和jsonpcallback參數(shù)書可以省略的,那樣的話jquery會(huì)自動(dòng)給你貼一個(gè)值
同時(shí)后端返回來的也就不再是那個(gè)f函數(shù)了。
那么問題又來了,不是說ajax請求就會(huì)出現(xiàn)跨域問題,那為什么我這個(gè)用ajax發(fā)送jsonp請求就沒有跨域呢?
答:我也不知道。然后就去查了一下jquery的文檔。文章來源:http://www.zghlxwxcb.cn/news/detail-420933.html
所以大概是因?yàn)闆]有用到XMLhttprequest這個(gè)對象,所以并不算一個(gè)真正的ajax請求把。文章來源地址http://www.zghlxwxcb.cn/news/detail-420933.html
到了這里,關(guān)于html前端跨域問題的解決方案的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!