天天躁日日躁狠狠躁AV麻豆-天天躁人人躁人人躁狂躁-天天澡夜夜澡人人澡-天天影视香色欲综合网-国产成人女人在线视频观看-国产成人女人视频在线观看

父子頁(yè)面之間跨域通信的方法

  由于同源策略的限制,JavaScript跨域的問(wèn)題,一直是一個(gè)比較棘手的問(wèn)題,為了解決頁(yè)面之間的跨域通信,大家煞費(fèi)苦心,研究了各種跨域方案。之前也有小網(wǎng)同學(xué)分享過(guò)一篇“跨域,不再糾結(jié)” 開始照著嘗試時(shí)還是有些不夠明白的地方,深入了解之后,這里給大家補(bǔ)充一點(diǎn)更具體的做法。

  先來(lái)看看哪些情況下才存在跨域的問(wèn)題:

  其中編號(hào)6、7兩種情況同屬于主域名相同的情況,可以設(shè)置domain來(lái)解決問(wèn)題,今天就不討論這種情況了。 對(duì)于其他跨域通信的問(wèn)題,我想又可以分成兩類:

  其一(第一種情況)是a.com下面的a.js試圖請(qǐng)求b.com下某個(gè)接口時(shí)產(chǎn)生的跨域問(wèn)題。

  其二(第二種情況)是當(dāng)a.com與b.com下面的頁(yè)面成父子頁(yè)面關(guān)系時(shí)試圖互相通信時(shí)產(chǎn)生的跨域問(wèn)題,典型的應(yīng)用場(chǎng)景如a.com/a.html使用iframe內(nèi)嵌了b.com/b.html,大家都知道a.html內(nèi)的js腳本試圖訪問(wèn)b.html時(shí)是會(huì)被拒絕的,反之亦然。

  第一種情況,目前主流的方案是JSONP,高版本瀏覽器支持html5的話,還可以使用XHR2支持跨域通信的新特性。

  第二種情況,目前主要是通過(guò)代理頁(yè)面或者使用postMessageAPI來(lái)做,這也是今天要討論的話題。 第二種情況,有這樣一些類似的案例:a.com/a.html使用iframe內(nèi)嵌了b.com/b.html,現(xiàn)在希望iframe的高度能自動(dòng)適應(yīng)b.html的高度,使iframe不要出現(xiàn)滾動(dòng)條。我們都知道跨域了,a.html是沒辦法直接讀取到b.html的高度的,b.html也沒辦法把自己的高度告訴a.html。 直接說(shuō)可以用代理頁(yè)面的方法搞定這個(gè)問(wèn)題吧,但是怎么代理法,先來(lái)看下面這張圖:

  b.html與a.html是不能直接通信的。我們可以在b.html下面再iframe內(nèi)嵌一個(gè)proxy.html頁(yè)面,因?yàn)檫@個(gè)頁(yè)面是放在a.com下面的,與a.html同域,所以它其實(shí)是可以和a.html直接通信的,假如a.html里面有定義一個(gè)方法_callback,在proxy.html可以直接top._callback()調(diào)用它。但是b.html本身和proxy.html也是不能直接通信的,所謂代理頁(yè)面的橋梁作用怎么實(shí)現(xiàn)呢? b.html內(nèi)嵌proxy.html是通過(guò)一段類似下面這樣的代碼: <iframe id=”proxy” src=”a.com/proxy.html” name=”proxy” frameborder=”0″ width=”0″ height=”0″></iframe> 這個(gè)iframe的src屬性b.html是有權(quán)限控制的。如果它把src設(shè)置成a.com/proxy.html?args=XXX,也就是給url加一個(gè)查詢字符串,proxy.html內(nèi)的js是可以讀取到的。對(duì)的,這個(gè)url的查詢字符串就是b.html和proxy.html之間通信的橋梁,美中不足的是每次通信都要重寫一次url造成一次網(wǎng)絡(luò)請(qǐng)求,這有時(shí)會(huì)對(duì)服務(wù)器及頁(yè)面的運(yùn)行效率產(chǎn)生很大的影響。同時(shí)由于參數(shù)是通過(guò)url來(lái)傳遞的,會(huì)有長(zhǎng)度和數(shù)據(jù)類型的限制,搜集的資料顯示:

  • IE瀏覽器對(duì)URL的長(zhǎng)度現(xiàn)限制為2048字節(jié)。
  • 360極速瀏覽器對(duì)URL的長(zhǎng)度限制為2118字節(jié)。
  • Firefox(Browser)對(duì)URL的長(zhǎng)度限制為65536字節(jié)。
  • Safari(Browser)對(duì)URL的長(zhǎng)度限制為80000字節(jié)。
  • Opera(Browser)對(duì)URL的長(zhǎng)度限制為190000字節(jié)。
  • Google(chrome)對(duì)URL的長(zhǎng)度限制為8182字節(jié)。

  上面的方法,通過(guò)迂回戰(zhàn)術(shù)實(shí)現(xiàn)了b.html跟a.html通信,但是倒過(guò)來(lái),a.html怎么跟b.html通信呢?嵌入在b.html里面的proxy.html可以用top快速的聯(lián)系上a.html,但是要想讓a.html找到proxy.html就不容易了,夾在中間的 b.html生生把它們分開了,a.html沒法讓b.html去找到proxy.html然后返回給它。只能采用更迂回的戰(zhàn)術(shù)了。 順著前面b.html到a.html的通信過(guò)程,逆向的想一下,雖然a.html沒有辦法主動(dòng)找到proxy.html,但是proxy.html可以反過(guò)來(lái)告訴a.html它在哪里: 在proxy.html加這么一段腳本:

  也就是必須由proxy.html先主動(dòng)發(fā)送一個(gè)消息給a.html,a.html得到proxy.html頁(yè)面window的引用,就可以反過(guò)來(lái)向它發(fā)送請(qǐng)求了。 現(xiàn)在a.html可以把消息發(fā)給proxy.html了,但是proxy.html怎么把消息轉(zhuǎn)送到b.html?似乎這才是難點(diǎn),因?yàn)樗鼈冎g才真正有著“跨域”這一道鴻溝。 這回我們不再用前面那個(gè)iframe內(nèi)嵌代理頁(yè)面的方法再在proxy.html內(nèi)嵌一個(gè)b.com下面的代理頁(yè)面了,這樣實(shí)在會(huì)給人感覺嵌的太深了,四層。但是為了跨越這道鴻溝,b.com下面也加一個(gè)代理頁(yè)面是免不的。不過(guò)現(xiàn)在我們要利用一下window.name。window.name有一個(gè)特性,就是頁(yè)面在同一個(gè)瀏覽器窗口(標(biāo)簽頁(yè))中跳轉(zhuǎn)時(shí),它一直存在而且值不會(huì)改變。比如我們?cè)赼.html中設(shè)置了window.name=”a”,然后location.href=”http://b.com/b.html”跳轉(zhuǎn)后,b.html可以讀取window.name的值為”a”;而且window.name的值長(zhǎng)度一般可以到達(dá)2M,ie和firefox甚至可以達(dá)到32M,這樣的存儲(chǔ)容量,足夠利用起來(lái)做跨域的數(shù)據(jù)傳遞了。好吧,我們現(xiàn)在要做的就是當(dāng)proxy.html拿到a.html發(fā)送過(guò)來(lái)的數(shù)據(jù)后把這個(gè)數(shù)據(jù)寫入window.name中,然后跳轉(zhuǎn)到b.com下面的代理頁(yè)面,我們這里假設(shè)是bproxy.html。bproxy.html讀取到window.name值后,通知給它父頁(yè)面b.html就簡(jiǎn)單了。我們?cè)賮?lái)看這個(gè)過(guò)程可以用圖大概示意一下:

  圖例中綠色的雙向箭頭表示可以通信,橙色的雙向箭頭表示不能直接通信。 最后我們簡(jiǎn)單看一下雙向通信的實(shí)測(cè)效果:

  b.html每次加載的時(shí)候都先給a.html發(fā)一個(gè)”連接請(qǐng)求”,讓a.html可以找到proxy.html。所以頁(yè)面第一次加載的時(shí)候會(huì)產(chǎn)生三個(gè)請(qǐng)求:

  每次b.html向a.html發(fā)送消息的時(shí)候會(huì)產(chǎn)生一個(gè)請(qǐng)求:

  每次a.html向b.html發(fā)送消息的時(shí)候會(huì)產(chǎn)生兩個(gè)請(qǐng)求,其中一個(gè)是a.com/proxy.html向b.com/bproxy.html跳轉(zhuǎn)產(chǎn)生的,另一個(gè)是b.html重新向a.html發(fā)起“連接請(qǐng)求”時(shí)產(chǎn)生的:

  最后簡(jiǎn)單看一下實(shí)測(cè)的幾個(gè)測(cè)試頁(yè)面代碼:

  代碼片段一,a.com/a.html:   

  代碼片段二,a.com/proxy.html:

  代碼片段三,b.com/b.html:

  代碼片段四,b.com/bproxy.html:

  好吧,現(xiàn)在我必須把話鋒調(diào)轉(zhuǎn)一下了。前面講的這么多,也只是拋出來(lái)一些之前我們可能會(huì)采用的跨域通信方法,事實(shí)上代理頁(yè)面、url傳參數(shù)和window.name、甚至還有一些利用url的hash值的跨域傳值方法,都能百度到不少相關(guān)資料。但它們都逃不開代理頁(yè)面,也就不可避免的要產(chǎn)生網(wǎng)絡(luò)請(qǐng)求,而事實(shí)上這并不是我們的本意,我們?cè)鞠M鼈兡軌蛑苯釉诳蛻舳送ㄐ牛苊獠槐匾?a href=/pingce/wangluo/ target=_blank class=infotextkey>網(wǎng)絡(luò)請(qǐng)求開銷——這些開銷,在訪問(wèn)量超大的站點(diǎn)可能會(huì)對(duì)服務(wù)器產(chǎn)生相當(dāng)大的壓力。那么,有沒有更完美一點(diǎn)的替代方案呢? 必須給大家推薦postMessage。postMessage 正是為了滿足一些合理的、不同站點(diǎn)之間的內(nèi)容能在瀏覽器端進(jìn)行交互的需求而設(shè)計(jì)的。利用postMessage API實(shí)現(xiàn)跨域通信非常簡(jiǎn)單,我們直接看一下實(shí)例的代碼:

  代碼片段五,A.com/a.html   

  代碼片段六,b.com/b.html:

  代碼的關(guān)鍵是message事件是一個(gè)擁有data(數(shù)據(jù))和origin(來(lái)源)屬性的DOM事件。data屬性是發(fā)送的實(shí)際數(shù)據(jù),origin屬性是發(fā)送來(lái)源。Origin屬性很關(guān)鍵,有了這個(gè)屬性,接收方可以輕易的忽略掉來(lái)自不可信源的消息,也就能有效避免跨域通信這個(gè)開口給我們的源安全帶來(lái)的隱患。接口很強(qiáng)大,所以代碼很簡(jiǎn)單。我們可以抓包看一下,這個(gè)通信過(guò)程完全是在瀏覽器端的,沒有產(chǎn)生任何的網(wǎng)絡(luò)請(qǐng)求。同時(shí)這個(gè)接口目前已經(jīng)得到了絕大多數(shù)瀏覽器的支持,包括IE8及以上版本,參見下面的圖表:

  但是為了覆蓋ie6等低版本瀏覽器,我們完整的方案里面還是要包含一下兼容代碼,就是最開始介紹的代理頁(yè)面的方法了,但必須是以postMessage為主,這樣即便最后會(huì)有某些瀏覽器因?yàn)檫@種通信產(chǎn)生一些網(wǎng)絡(luò)請(qǐng)求,比例也是非常低的了。

it知識(shí)庫(kù)父子頁(yè)面之間跨域通信的方法,轉(zhuǎn)載需保留來(lái)源!

鄭重聲明:本文版權(quán)歸原作者所有,轉(zhuǎn)載文章僅為傳播更多信息之目的,如作者信息標(biāo)記有誤,請(qǐng)第一時(shí)間聯(lián)系我們修改或刪除,多謝。

主站蜘蛛池模板: 动漫美女人物被黄漫在线看 | 午夜DV内射一区二区 | 中国欧美日韩一区二区三区 | 久久一本岛在免费线观看2020 | 国产午夜一级淫片 | 美女大鸡鸡| 男人到天堂a线牛叉在线 | 中国女人精69xxxxxx视频 | 动漫美女3d被爆漫画 | 爱豆剧果冻传媒在线播放 | 4399日本电影完整版在线观看免费 | 亚洲成人三级 | 国产精品人妻无码久久久2022 | 欧美日韩一区在线观看 | 99在线免费| 国产成人免费网站在线观看 | 国产中文字幕乱码免费 | 日韩精品久久久久久久电影 | 国产精品一库二库三库 | 超碰在线97av视频免费 | 久久国产36精品色熟妇 | 亚洲爆乳少妇精品无码专区 | 午夜婷婷一夜七次郎 | 伊人色综合久久天天网 | 国产精品2020观看久久 | 亚洲精品无码久久久久A片 亚洲精品无码国产爽快A片百度 | 香蕉精品国产高清自在自线 | 国产亚洲精品久久久久久国模美 | 一起洗澡的老师免费播放 | 99在线免费视频 | 久久伊人中文字幕有码 | 国产精品青青在线麻豆 | 久久久久久久国产精品视频 | 校园高h肉耽文 | 国产精品成人网 | 99精品网站 | 伊人网站在线 | 777EY_卡通动漫_1页 | 精品无码乱码AV | 少妇第一次交换 | 亚洲精品国产自在在线观看 |