成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

iframe解決跨域ajax請(qǐng)求的方法

cncoder / 1978人閱讀

摘要:數(shù)據(jù)仍然是通過(guò)頁(yè)面獲得,頁(yè)面僅需向頁(yè)面?zhèn)鬟f即可,頁(yè)面拿到函數(shù)名,并通過(guò)傳遞從服務(wù)器拿到的數(shù)據(jù),在頁(yè)面執(zhí)行頁(yè)面的回調(diào)函數(shù),回調(diào)函數(shù)執(zhí)行完畢后移除頁(yè)面以及該函數(shù)。以上是我所知道的解決跨域請(qǐng)求的兩種方法。

iframe跨域的基本前提是,一個(gè)頁(yè)面可以嵌套非同源站點(diǎn)的html文件,以及某一個(gè)域名下的html頁(yè)面可以通過(guò)腳本向同域名服務(wù)器發(fā)出ajax請(qǐng)求。當(dāng)一個(gè)域名為domain1下的頁(yè)面A想要向domain2發(fā)出ajax請(qǐng)求時(shí),由于同源策略的限制無(wú)法直接請(qǐng)求到數(shù)據(jù),但是可以在頁(yè)面A中動(dòng)態(tài)添加一個(gè)display設(shè)置為none的iframe,該iframe的src為domain2下的html頁(yè)面B,由頁(yè)面B來(lái)發(fā)出ajax請(qǐng)求,因?yàn)轫?yè)面B是domain2下的所以可以成功發(fā)出請(qǐng)求。當(dāng)B頁(yè)面拿到數(shù)據(jù)之后再傳遞給A頁(yè)面。

可以利用HTML5的postMessage來(lái)向A頁(yè)面?zhèn)鬟f數(shù)據(jù)。
將通過(guò)一個(gè)demo來(lái)具體說(shuō)明如何操作,該demo涉及到兩個(gè)域名 http://localhost:3000 以及 http://127.0.0.1:3001。向 http://localhost:3000/a.html中嵌入 http://127.0.0.1:3001/b.html頁(yè)面,在 http://127.0.0.1:3001/b.html發(fā)出本域名下的ajax請(qǐng)求。

先舉一個(gè)簡(jiǎn)單的例子。

a.html:




    
    Title





b.html:




    
    Title
    




a頁(yè)面中直接嵌入b頁(yè)面,b頁(yè)面加載后執(zhí)行腳本,向同源服務(wù)器發(fā)出請(qǐng)求,拿到數(shù)據(jù)后發(fā)送給a頁(yè)面。
這里強(qiáng)調(diào)一下:
1.代碼中寫(xiě)的是window.parent而非window
2.代碼中的第二個(gè)參數(shù)寫(xiě)為"*",也可以指定精確的目標(biāo)origin

當(dāng)然實(shí)際開(kāi)發(fā)中一個(gè)頁(yè)面要發(fā)出很多個(gè)請(qǐng)求,并且根據(jù)用戶操作不同可能要發(fā)出不一樣的請(qǐng)求,所以需要進(jìn)一步的封裝。

a頁(yè)面通過(guò)b頁(yè)面發(fā)出請(qǐng)求,這需要將發(fā)送請(qǐng)求的url以及請(qǐng)求的類型和請(qǐng)求參數(shù)等信息傳遞到b頁(yè)面,可以直接通過(guò)嵌入的iframe的src來(lái)傳遞,然后b頁(yè)面根據(jù)location.search的值來(lái)獲取以上的信息。

我們的目標(biāo)是構(gòu)建一個(gè)形如iframeAjax(params,cb)的函數(shù)。
其中params中,包括了b頁(yè)面的url,ajax請(qǐng)求的最終目標(biāo)url,ajax請(qǐng)求的種類,以及ajax請(qǐng)求的參數(shù)。
格式如下:

let {targetUrl, queryUrl, type, data = {}} = params

剛才已經(jīng)提到過(guò),a頁(yè)面通過(guò)設(shè)置iframe的src來(lái)向b頁(yè)面?zhèn)鬟f各種參數(shù)。
我們將type以及queryUrl合并到data中:

Object.assign(data, {type, queryUrl});

接下來(lái)就可以構(gòu)建完整的iframe的src

let url = targetUrl + "?" + serialize(data);    //雖然叫url但實(shí)際是iframe的src

然后我們封裝一個(gè)建立frame的方法。

function createIframe(url, cb) {
    let iframe = document.createElement("iframe");
    iframe.style.display = "none";
    iframe.src = url;
    document.body.appendChild(iframe);

    function handleIframe(e) {
      cb(e.data);
      document.body.removeChild(iframe);
      window.removeEventListener("message", handleIframe);
    }

    window.addEventListener("message", handleIframe);
}

在這個(gè)方法中,我們創(chuàng)建了一個(gè)iframe設(shè)置其display為none使其不可見(jiàn),設(shè)置了其src,并且把它添加到了頁(yè)面上。又給window添加了事件監(jiān)聽(tīng),當(dāng)收到b頁(yè)面?zhèn)鱽?lái)的數(shù)據(jù)之后,調(diào)用數(shù)據(jù)處理的函數(shù)cb并且傳入數(shù)據(jù)作為其參數(shù)。當(dāng)cb執(zhí)行完畢之后,移除iframe,并移除事件監(jiān)聽(tīng)。

b頁(yè)面中我們的任務(wù)是,拿到location.search的并正確的解析為一個(gè)對(duì)象,該對(duì)象包含了{(lán)type,queryUrl,data} 其中type是ajax的類型,queryUrl是ajax的目標(biāo)url,data是請(qǐng)求的參數(shù)。

通過(guò)一個(gè)parseSearch的方法解析location.search。

function parseSearch() {
    let search = location.search.slice(1);
    let keyValuePairArr = search.split("&");
    let obj = {};

    keyValuePairArr.forEach(pair => {
      let [key, value] = pair.split("=");
      obj[decodeURIComponent(key)] = decodeURIComponent(value);
    });
    return obj;
}

我們還需要一個(gè)方法來(lái)移除其中的type和queryUrl,只剩下ajax請(qǐng)求的參數(shù)。

function getParams(obj) {
    delete obj.type;
    delete obj.queryUrl;
    return obj;
}

然后我們就可以解析location.search得到信息對(duì)象,并且發(fā)出ajax請(qǐng)求來(lái)拿到服務(wù)器的數(shù)據(jù)了。

$.ajax({
    type: obj.type,
    url: obj.queryUrl,
    data: getParams(obj)
  }).done(data => {
    window.parent.postMessage(data, "*");
});

再次鞏固一下整個(gè)流程,domain1下的a頁(yè)面向domain2發(fā)出動(dòng)態(tài)ajax請(qǐng)求的中間過(guò)程:
在a頁(yè)面下封裝b頁(yè)面完整url,ajax請(qǐng)求的type,ajax請(qǐng)求的最終url,以及ajax請(qǐng)求的數(shù)據(jù)等信息。通過(guò)設(shè)置iframe的src將這些信息帶到b頁(yè)面,b頁(yè)面解析這些信息,最后向服務(wù)器發(fā)出ajax請(qǐng)求并將結(jié)果通過(guò)postMessage的API帶回給a頁(yè)面,a頁(yè)面收到數(shù)據(jù)后處理數(shù)據(jù),處理完畢移除iframe,移除事件監(jiān)聽(tīng)。

除了利用postMessage API之外,還可以通過(guò)iframe + window.name來(lái)實(shí)現(xiàn)跨域ajax請(qǐng)求。
當(dāng)a頁(yè)面中有一個(gè)b頁(yè)面的iframe時(shí),兩個(gè)頁(yè)面共享window.name。在b頁(yè)面拿到數(shù)據(jù)后賦值給window.name。但是由于不使用postMessage API,數(shù)據(jù)無(wú)法傳輸給a頁(yè)面。我們可以將location.href轉(zhuǎn)為domain1(a頁(yè)面所在的域名)下的c頁(yè)面,由c頁(yè)面調(diào)用a頁(yè)面的回調(diào)方法。

先舉一個(gè)簡(jiǎn)單的例子:

a頁(yè)面:




    
    Title





b頁(yè)面:




    
    Title
    




c頁(yè)面:




    
    Title




很簡(jiǎn)單的例子,a頁(yè)面中定義一個(gè)方法print,并嵌入一個(gè)frame,frame為b頁(yè)面,b頁(yè)面向服務(wù)器拿到數(shù)據(jù)后,賦值給window.name,然后再打開(kāi)c頁(yè)面,在c頁(yè)面調(diào)用父頁(yè)面a中的print方法,并將拿到的數(shù)據(jù)作為參數(shù)傳入。
不知道為啥,ajax請(qǐng)求返回的對(duì)象不經(jīng)處理直接賦值最終輸出結(jié)果是[object Object]。因此在這里先stringify之后再parse。

封裝之后的代碼如下:

aa頁(yè)面:




    
    Title




bb頁(yè)面:




    
    Title
    




c頁(yè)面:




    
    Title




不同于使用postMessage,當(dāng)通過(guò)window.name通信時(shí),由于傳入的回調(diào)函數(shù)是在頁(yè)面c執(zhí)行,因此需要把回調(diào)函數(shù)的函數(shù)名作為參數(shù)傳過(guò)來(lái),并且也要把頁(yè)面c的url地址作為參數(shù)傳入。數(shù)據(jù)仍然是通過(guò)bb頁(yè)面獲得,bb頁(yè)面僅需向c頁(yè)面?zhèn)鬟ffuncName即可,c頁(yè)面拿到函數(shù)名,并通過(guò)window.name傳遞從服務(wù)器拿到的數(shù)據(jù),在c頁(yè)面執(zhí)行aa頁(yè)面的回調(diào)函數(shù),回調(diào)函數(shù)執(zhí)行完畢后移除aa頁(yè)面iframe以及該函數(shù)。

注意:不能在bb頁(yè)面直接調(diào)用parent頁(yè)面aa的函數(shù) 由于aa與bb是非同源的,因此會(huì)報(bào)錯(cuò)。必須由一個(gè)與aa頁(yè)面同源的頁(yè)面cc頁(yè)面,來(lái)執(zhí)行在aa頁(yè)面中注冊(cè)的函數(shù)。

以上是我所知道的iframe解決跨域ajax請(qǐng)求的兩種方法。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/93179.html

相關(guān)文章

  • 利用iframe實(shí)現(xiàn)ajax跨域請(qǐng)求,抓取網(wǎng)頁(yè)中ajax數(shù)據(jù)

    摘要:如何利用網(wǎng)頁(yè)請(qǐng)求暴露出來(lái)的接口去抓取網(wǎng)頁(yè)數(shù)據(jù)很多爬蟲(chóng)都能實(shí)現(xiàn)這個(gè)功能??缬蛲ㄐ艜r(shí),瀏覽器會(huì)報(bào)如下錯(cuò)誤其實(shí)這兩個(gè)問(wèn)題都是由于跨域造成的。結(jié)果這些數(shù)據(jù)可以在請(qǐng)求成功會(huì)傳回本地。 如何利用網(wǎng)頁(yè)ajax請(qǐng)求暴露出來(lái)的接口去抓取網(wǎng)頁(yè)數(shù)據(jù)?很多爬蟲(chóng)都能實(shí)現(xiàn)這個(gè)功能。不過(guò)今天要來(lái)和大家八一八單從前端的角度,利用js解決這個(gè)問(wèn)題。 大家都知道,在不同域的情況下是不能發(fā)送ajax請(qǐng)求的,瀏覽器會(huì)報(bào)如下錯(cuò)...

    Heier 評(píng)論0 收藏0
  • JS跨域

    摘要:跨域概述兩個(gè)不同域互相請(qǐng)求,稱為跨域,是由瀏覽器同源策略限制的一類請(qǐng)求場(chǎng)景。同源策略限制以下幾種行為和無(wú)法讀取無(wú)法獲得請(qǐng)求不能發(fā)送目前主流的用于解決跨域問(wèn)題的方法跨域缺點(diǎn)這種方法只適用于和窗口,和無(wú)法通過(guò)這種方法。 跨域概述 兩個(gè)不同域互相請(qǐng)求,稱為跨域,是由瀏覽器同源策略限制的一類請(qǐng)求場(chǎng)景。 --> 同源策略/SOP(Same origin policy)是瀏覽器最核心也最基本的安全...

    whataa 評(píng)論0 收藏0
  • 前端跨域整理

    摘要:前言原文地址前端跨域總結(jié)博主博客地址的個(gè)人博客相信每一個(gè)前端對(duì)于跨域這兩個(gè)字都不會(huì)陌生,在實(shí)際項(xiàng)目中應(yīng)用也是比較多的。通過(guò)跨域前面說(shuō)過(guò)了,瀏覽器有一個(gè)同源策略,其限制之一是不能通過(guò)的方法去請(qǐng)求不同源中的文檔。 前言 原文地址:前端跨域總結(jié) 博主博客地址:Damonare的個(gè)人博客 相信每一個(gè)前端er對(duì)于跨域這兩個(gè)字都不會(huì)陌生,在實(shí)際項(xiàng)目中應(yīng)用也是比較多的。但跨域方法的多種多樣實(shí)在讓人目...

    yankeys 評(píng)論0 收藏0
  • 前端跨域整理

    摘要:前言原文地址前端跨域總結(jié)博主博客地址的個(gè)人博客相信每一個(gè)前端對(duì)于跨域這兩個(gè)字都不會(huì)陌生,在實(shí)際項(xiàng)目中應(yīng)用也是比較多的。通過(guò)跨域前面說(shuō)過(guò)了,瀏覽器有一個(gè)同源策略,其限制之一是不能通過(guò)的方法去請(qǐng)求不同源中的文檔。 前言 原文地址:前端跨域總結(jié) 博主博客地址:Damonare的個(gè)人博客 相信每一個(gè)前端er對(duì)于跨域這兩個(gè)字都不會(huì)陌生,在實(shí)際項(xiàng)目中應(yīng)用也是比較多的。但跨域方法的多種多樣實(shí)在讓人目...

    jsliang 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

cncoder

|高級(jí)講師

TA的文章

閱讀更多
最新活動(dòng)
閱讀需要支付1元查看
<