Ajax不能跨域訪問的解決方案

文章介紹

這是一篇客税,引導(dǎo)文吧... 因?yàn)閷戇@篇文章時况褪,實(shí)在想不出該如何分序。因此以實(shí)現(xiàn)跨域訪問為目的更耻,從基礎(chǔ)知識往上寫测垛。最后以百度搜索智能提示為例,來講解跨域的具體應(yīng)用秧均!

內(nèi)容

首先食侮,我們得明確什么是跨域,這里先了解一下url中各組成部分
以百度為例:

https://www.baidu.com:80

協(xié)議:https://
二級域名:www
一級域名:baidu.com
端口號:80

以上4個有一個不同即為跨域訪問目胡,比如你當(dāng)前頁面在https://www.baidu.com:80锯七,你去用Ajax請求https://tieba.baidu.com:80的數(shù)據(jù),就相當(dāng)于跨域訪問誉己!

在Ajax中眉尸,是不支持跨域訪問的,所以www.baidu.com拿不到tieba.baidu.com上的數(shù)據(jù)巨双。

那么這里就要用到跨域訪問的技巧噪猾,雖然Ajax不支持筑累,但我們可以利用src這個屬性達(dá)到目的袱蜡。

對于src這個屬性,相信很多人都會想到img標(biāo)簽慢宗!我們都知道img標(biāo)簽的src如果設(shè)置為一個網(wǎng)絡(luò)地址時戒劫,那么就會去使用該網(wǎng)絡(luò)地址的圖片資源。

比如src=https://ss0.bdstatic.com/5aV1bjqh_Q23odCf/static/superman/img/logo/bd_logo1_31bdc765.png

那么img標(biāo)簽就會請求該url的數(shù)據(jù)返回來婆廊,其實(shí)這就已經(jīng)是跨域訪問了。因?yàn)槟惝?dāng)前的頁面并不在https://ss0.bdstatic.com上巫橄,但你卻成功訪問到了它的資源淘邻。

因此我們可以利用src這個利器,達(dá)到我們跨域訪問的目的湘换。

不過使用src之前宾舅,得先了解一下Ajax利用請求回來的響應(yīng)數(shù)據(jù)執(zhí)行回調(diào)的一種方法:

//先定義一個函數(shù),等會利用該函數(shù)執(zhí)行回調(diào)
function fun (obj) {
    console.log(obj);
}
//以下均為ajax請求彩倚,粗略看即可
var url = 'test.php';//訪問當(dāng)前目錄的php文件
var xhr = new XMLHttpRequest();
xhr.open('get',url);
xhr.send();
xhr.onreadystatechange = function () {
    if (xhr.readyState == 4) {
        if (xhr.status >=200 && xhr.status <300 || xhr.status == 304) {
            //請求成功后,拿到返回字符串并使用eval執(zhí)行
            eval(xhr.responseText);
        } else {
            console.log('請求失敗');
        }
    }
}

為了拿到請求數(shù)據(jù)筹我,下面我們利用php簡單制作一個后端接口test.php

<?php
//創(chuàng)建一個php對象 name:kevin,age:23
$obj = array("name"=>"Kevin","age"=>"23");
//將php對象編碼為json格式的字符串
$json = json_encode($obj);
//后端給客戶端返回一個字符串  點(diǎn)為字符串拼接(相當(dāng)于js中加號)
echo("fun(" . $json . ")");

請求成功后eval(xhr.responseText);這一句可以一步步分解為如下代碼:

  1. eval(xhr.responseText);
  2. eval(fun({"name":"Kevin", "age":"23"}));
  3. fun({"name":"Kevin", "age":"23"});
  4. console.log({"name":"Kevin", "age":"23"})

因此控制臺打印如下:

瀏覽器控制臺

以上我們實(shí)現(xiàn)了:根據(jù)后端返回的數(shù)據(jù)來決定具體執(zhí)行某一個函數(shù),并且利用請求回來的數(shù)據(jù)傳參帆离!

但是以上并沒有解決我們跨域需求蔬蕊,因?yàn)槲艺埱蟮?strong>后端接口,依然在當(dāng)前域哥谷!

那么我剛才說了岸夯,利用src麻献,我們就能實(shí)現(xiàn)跨域。假如我們使用img標(biāo)簽猜扮,使其src="test.php"勉吻。這樣我們雖然拿到了數(shù)據(jù),但是img標(biāo)簽并不會像eval函數(shù)一樣幫我們執(zhí)行數(shù)據(jù)旅赢,這樣數(shù)據(jù)就得不到利用齿桃。

所以對于實(shí)現(xiàn)跨域,我們有這樣的需求:

  1. 有src屬性
  2. 可以像eval函數(shù)一樣將數(shù)據(jù)執(zhí)行煮盼!

滿足以上條件的確實(shí)有短纵,那就是script標(biāo)簽。

平時我們在script標(biāo)簽內(nèi)寫代碼孕似,其實(shí)寫的就是字符串踩娘,并且script標(biāo)簽會幫我們執(zhí)行。

并且我們平時經(jīng)常會用到script標(biāo)簽的src屬性喉祭,比如引入框架時养渴,下面以jQuery為例:
<script src="./jquery.js"></script>

其實(shí)它就相當(dāng)于執(zhí)行了如下:

<script>
    //一大堆jQ代碼字符串...
</script>

因此我們可以利用script標(biāo)簽就行跨域訪問,這里以百度為例:

這是百度搜索時泛烙,搜索提示的數(shù)據(jù)接口

https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su?wd=關(guān)鍵字&cb=方法名

比如我搜索a理卑,頁面如下:

百度搜索提示

那么我利用接口url也會得到上面數(shù)據(jù),如圖:

接口獲取的數(shù)據(jù)

這里方法名會根據(jù)我們的參數(shù)返回蔽氨,因此你請求數(shù)據(jù)成功后要執(zhí)行什么函數(shù)藐唠,那么就往cb傳該函數(shù)的方法名!

下面我用盡量少的代碼實(shí)現(xiàn)一下 百度搜索提示

<body>
<!--搜索框-->
<input type="text" id="input">
<!--數(shù)據(jù)請求回來后鹉究,往里面添加li-->
<ul id="ul"></ul>

<script>

//回調(diào)方法,數(shù)據(jù)返回后觸發(fā)
    function callBack(obj) {
        //從上面圖知道關(guān)鍵字?jǐn)?shù)組位于數(shù)據(jù)的s屬性中
        var array = obj.s;
        //每次觸發(fā)先清空以前數(shù)據(jù),再添加
        ul.innerHTML = "";
        for (var i = 0; i < array.length; i++) {
            var li = document.createElement('li');
            li.innerText = array[i];
            ul.appendChild(li);
        }
    }

    //url1 和 url2 為了以后方便拼接
    var url1 = 'https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su?wd=';
    var url2 = '&cb=';
    var ul = document.getElementById('ul');
    var input = document.getElementById('input');
    //監(jiān)聽輸出框的鍵盤輸入
    input.onkeyup = function () {
    //創(chuàng)建script標(biāo)簽
        var script = document.createElement('script');
        //把輸入框的值和方法名作為url參數(shù)
        script.src = url1 + this.value+ url2 + callBack.name;
        //把script標(biāo)簽添加到body,那么就會執(zhí)行代碼
        document.body.appendChild(script);
        };
</script>
</body>

最后實(shí)現(xiàn)效果如下:

效果

代碼僅以實(shí)現(xiàn)效果為目的宇立,寫得很簡短,大家可以直接拷貝到自己電腦嘗試~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末自赔,一起剝皮案震驚了整個濱河市妈嘹,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌绍妨,老刑警劉巖润脸,帶你破解...
    沈念sama閱讀 217,826評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異他去,居然都是意外死亡毙驯,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,968評論 3 395
  • 文/潘曉璐 我一進(jìn)店門灾测,熙熙樓的掌柜王于貴愁眉苦臉地迎上來爆价,“玉大人,你說我怎么就攤上這事≡始幔” “怎么了魂那?”我有些...
    開封第一講書人閱讀 164,234評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長稠项。 經(jīng)常有香客問我涯雅,道長,這世上最難降的妖魔是什么展运? 我笑而不...
    開封第一講書人閱讀 58,562評論 1 293
  • 正文 為了忘掉前任活逆,我火速辦了婚禮,結(jié)果婚禮上拗胜,老公的妹妹穿的比我還像新娘蔗候。我一直安慰自己,他們只是感情好埂软,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,611評論 6 392
  • 文/花漫 我一把揭開白布锈遥。 她就那樣靜靜地躺著,像睡著了一般勘畔。 火紅的嫁衣襯著肌膚如雪所灸。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,482評論 1 302
  • 那天炫七,我揣著相機(jī)與錄音爬立,去河邊找鬼。 笑死万哪,一個胖子當(dāng)著我的面吹牛侠驯,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播奕巍,決...
    沈念sama閱讀 40,271評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼吟策,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了的止?” 一聲冷哼從身側(cè)響起踊挠,我...
    開封第一講書人閱讀 39,166評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎冲杀,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體睹酌,經(jīng)...
    沈念sama閱讀 45,608評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡权谁,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,814評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了憋沿。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片旺芽。...
    茶點(diǎn)故事閱讀 39,926評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出采章,到底是詐尸還是另有隱情运嗜,我是刑警寧澤,帶...
    沈念sama閱讀 35,644評論 5 346
  • 正文 年R本政府宣布悯舟,位于F島的核電站担租,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏抵怎。R本人自食惡果不足惜奋救,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,249評論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望反惕。 院中可真熱鬧尝艘,春花似錦、人聲如沸姿染。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,866評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽悬赏。三九已至狡汉,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間舷嗡,已是汗流浹背轴猎。 一陣腳步聲響...
    開封第一講書人閱讀 32,991評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留进萄,地道東北人捻脖。 一個月前我還...
    沈念sama閱讀 48,063評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像中鼠,于是被迫代替她去往敵國和親可婶。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,871評論 2 354

推薦閱讀更多精彩內(nèi)容