日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Iframe中跨域进行父子窗口进行通信的四种方法

發布時間:2024/5/14 编程问答 47 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Iframe中跨域进行父子窗口进行通信的四种方法 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

?一、跨域簡介

? ? 1. 首先簡單介紹一下什么是跨域

? ? ? ? ? ? ? ? 當我們在瀏覽器的地址欄中輸入一個地址的時候,這個地址通常包含四部分信息內容。這四部分信息包含:①協議、②域名、③端口、④資源位置。

? ? ? ? ? ? ? ? 其中前三部分將會決定是否存在跨域,即:協議、域名、端口。如果其中有一個不一樣,瀏覽器就會認為存在跨域的問題。例如:

域名1域名2是否有跨域
http://father.moxiao.com/a/a.htmlhttp://father.moxiao.com/b/b.html不存在跨域
https://father.moxiao.com/a/a.htmlhttp://father.moxiao.com/b/b.html存在跨域,協議不一樣
http://father.moxiao.com/a/a.htmlhttp://child.moxiao.com/b/b.html存在跨域,域名不一樣
http://father.moxiao.com/a/a.htmlhttp://child.moxiao.com:8082/b/b.html存在跨域,端口不一樣

? ? 2.跨域的種類

????????????????一般有兩種形式的跨域問題:

???????????????????①使用XmlHttpRequest(XHR)或者使用AJAX發送的POST或者GET請求。這種形式的跨域是:前端頁面后端進行的跨域請求。這種形式跨域不在本篇文章的討論范圍內。

???????????????????②父子頁面之間進行的DOM操作(父子窗口之間的document操作)。這種形式的跨域是:前端頁面與前端頁面之間的通信或者相互操作的形成跨域。(本文主要討論就是這個話題

? ? 3.跨域的提示

? ? ? ? ? ? ? ? 如果在頁面上出現了上面任何一種形式的跨域,一般會在瀏覽器的控制臺(Chrome中按F12鍵)打印下面一段類似的描述:(一般包含accessing a cross-origin類似的信息就是跨域了)

二、問題描述

? ? 1.父子頁面之間的DOM操作

?????????在HTML頁面中,我們有時候會使用<iframe>標簽打開一個子窗口,又或者使用window.open方法打開一個子窗口,但有時想讓父子窗口之間進行通信。例如:根據父窗口的大小,對<iframe>子窗口大小進行設置等問題。

? ? ? ? ? ? ①、如果<iframe>中src屬性配置的地址和父窗口在同一個域下,可以在子窗口中通過window.parent.document來獲取父窗口的DOM對象。亦或父窗口也可以通過contentWindow屬性獲取子窗口的DOM對象(Iframe情況下)。例如:document.getElementById('iframe標簽的ID').contentWindow。兩者之間操作不會出現任何跨域的問題,可以自由的獲取任意想要的元素信息內容。也就不在本篇文章的討論范圍內。

? ? ? ? ? ? ?②、如果<iframe>中的src屬性配置的地址與父窗口不在同一個域下,即:協議、域名、端口任何一個不一樣都會造成跨域問題。當使用window.parent.document進行操作的時候,就會提示跨域的問題,就是上面截圖的信息內容。又或者使用contentWindow屬性也會提示相同的跨域問題。有以下幾種解決問題的方法以及這些方法的局限性。

三、解決頁面之間跨域問題的方法

? ? ? ? 著重看第一和第二種方法,在第一種和第二種方法無法使用的時候,可以考慮剩下的方法。

? ? 1. 使用document.domain方法(☆☆☆☆☆

? ? ? ? 1.1. document.domain的原理

? ? ? ? ? ? ?JS在判斷頁面之間是否有跨域操作,主要根據頁面的document.domain屬性進行對比來判斷是否有跨域。

?????????????如果兩個頁面的document.domain屬性值一樣的話,就算兩個頁面實際上不在同一個域下,JS也會認為他們之間沒有跨域操作。這樣的話,如果我們將兩個頁面的document.domain屬性值設置為一樣的。不同域下的頁面之間操作就可以像在一個域名下的頁面之間的操作。

? ? ? ? ? ? document.domain的默認值為:當前域名

? ? ?1.2.?document.domain的局限性

? ? ? ? ? ? 上面說如果將兩個頁面的document.domain屬性設置為一樣的話,就算實際上不在同一個域下,他們也可以進行DOM對象之間的操作。但是document.domain也不是你想設置成什么就可以設置成什么的,這個屬性的屬性值有一定的設置規則,如果不滿足設置的規則就不能設置成功。

? ? ? ? ? ? 規則如下:

? ? ? ? ? ? ?①document.domain只設置域名或者IP地址。即:沒有協議(http/https),沒有端口。

? ? ? ? ? ? ?②如果訪問的地址是域名形式,則document.domain只能設置為當前域名下的同級或者父級域名,并且不能設置為頂級域名也不可以設置為其他形式的域名(不是當前域名的父級或同級)。

?????????????????例如:當前訪問地址為:https://mp.csdn.net/mp_blog/creation/editor/121540023(當前頁面)。可以打開Chrome的控制臺(F12)找到console的tab。默認情況下,我們輸入document.domain會顯示‘csdn.net’。其中csdn.net就是https://mp.csdn.net的父級域名。我們也可以設置為mp.csdn.net。因為mp.csdn.net是mp.csdn.net的同級域名。

? ? ? ? ? ? ? ? ?但是我們不能設置頂級域名,即document.domain='net',就會提示錯誤信息。也不能設置其他的域名形式。即document.domain='csdn1.net'或者document.domain='baidu.com'。提示也說得很清楚。必須是mp.csdn.net的一個后綴形式。

? ? ? ? ? ? ? ③如果訪問地址是IP的形式,則document.domain只能設置一樣的IP地址。

? ? ? ? ? ? ? 下圖就是在當前頁面進行的設置。

? ? ? ? ? ? ?注意:根據上面的設置規則,在使用document.domain的方式時,頁面之間必須有相同的父級域名。否則這種方式將無法進行操作。

  • document.domain只配置域名或者IP地址,不需要配置協議、端口。
  • 因為document.domain只配置的域名或者IP地址,所以頁面之間的協議必須是一樣的,要么都是HTTP,要么都是HTTPS。如果是混合的,這種方式也是不行的。但是頁面端口可以不一樣。

? ? 1.3. domian方式的演示示例

????????https://github.com/1997chang/iframeCrossAccess是一個進行頁面操作跨域的顯示示例。該項目有兩個模塊,fathermodule和childmodule。

? ? ? ?在static/domain文件夾下顯示的為document.domain的解決方案的示例。

? ? ? 啟動father以及child模塊,在地址欄中輸入:father.moxiao.com:8081/domain/fatherDomainMethod.html。就可以進行頁面之間的相互操作了。

? ? 2. 使用postMessage方式(☆☆☆☆☆

? ? ? ? ?在H5之后,window對象添加了一個postMessage的方法,使用postMessage方法可以向任何域名發送消息內容(字符串或者對象)。postMessage方法發送的消息將不會受到跨域的影響。

? ? ? ? 2.1 postMessage不受跨域的影響

? ? ? ? ? ? 在HTML頁面中,可以在當前頁面中使用window.parent獲取父級窗口對象(WIndow),從而向父級窗口發送消息(子->父)。同樣也可以使用contentWindow獲取Iframe的打開的子窗口對象,從而向子窗口發送消息。(父->子

? ? ? ? ? ? 在父窗口中獲取其子窗口的window對象,又或者在子窗口中獲取其父窗口的window對象。但是如果兩個父子窗口存在跨域問題,那么將不能對獲取到的window對象進行任何操作。即可以在跨域的情況下獲取其子窗口或者父窗口的window對象,但是不能對獲取到的window對象進行任何操作。如果進行了任何的操作,都會提示跨域的問題。但是有兩個是例外。即使在跨域的情況下也可以對其進行設置。

????????????????①location屬性:設置window準備跳轉的頁面。后面兩種解決方法使用該屬性。

????????????????②postMessage方法,H5之后添加的。

? ? ? ? ? ? 無論當前域名是什么,獲取到的window對象的域名是什么。即使這兩個域名之間存在跨域問題,在window對象中有一個屬性location的設置和一個方法postMessage的調用不會受到跨域的影響。

? ? ? 2.2. postMessage方法的使用

? ? ? ? ? ? ?postMessage和addEventListener方法配合使用。postMessage是用來發送消息的,addEventListener是用來接收消息時候的回調。

? ? ? ? ? ? ?postMessage方法有兩個參數:

? ? ? ? ? ? ? ? ①發送的消息:可以是字符串,也可以是對象。

? ? ? ? ? ? ? ? ②接收消息的域名:要么是具體值(協議、域名、端口都要設置,且相同),要么是*。如果設置為*:則表示沒有任何限制。如果設置為具體值的話,則必須與發送到的窗口域名相同,包含協議、域名、端口,如果有一個不同的話,就會發送不出去。

? ? ? ? ? ? ? ? ? ? ? ? 例如:parent.window.postMessage('父窗口你好','http://father.moxiao.com'),就會提示錯誤。因為parent.window窗口的域名為:http://father.moxiao.com:8082,而發送配置的域名是:http://father.moxiao.com。就會提示下面的錯誤信息:

? ? ? ? ? ? ?例如:????????????????

parent.window.postMessage(content, 'http://father.moxiao.com:8081');

? ? ? ? ? ? ?addEventListener方法有兩個參數:

? ? ? ? ? ? ? ? ①監聽的時間類型:對于發送消息而言,固定為message。

? ? ? ? ? ? ? ? ②回調函數:在回調函數中一個參數event,event其中包含三個重要的屬性:

? ? ? ? ? ? ? ? ? ? ? ? 1.data:表示接受到的消息內容,可能是字符串,可能是對象,取決有發送方。

? ? ? ? ? ? ? ? ? ? ? ? 2.origin:String類型,表示發送消息的域名地址

? ? ? ? ? ? ? ? ? ? ? ? 3.source:對象,表示發送消息的窗口對象。

? ? ? ? ? ? ? ? 例如:

window.addEventListener('message', (event) => {$("#child").text($("#child").text() + '由' + event.origin + "發送過來的消息為:"+event.data); });

? ? ? ?2.3. postMessage的演示示例:

????????????????https://github.com/1997chang/iframeCrossAccess中static下的postMessage文件夾下。啟動項目之后,在地址欄中訪問:http://father.moxiao.com:8081/postmessage/fatherPostmessage.html地址,就可以進行父子窗口發送消息。顯示如下:

? ? 3.使用window.name屬性(☆☆☆

? ? ? ? window.name用于表示當前窗口的名稱。可以容納2M的大小內容。注意:在跨域的情況下,不能設置window.name的屬性值,也不能獲取其中的屬性值。一般window.name屬性要配合window.location屬性進行操作。

? ? ? ? 3.1. window.name屬性進行消息傳遞的原理

? ? ? ? ? ? ? ? window.name表示當前窗口的名稱。一個窗口在沒有關閉之前,可以在地址欄中進行多次地址改變。但是他們都共享同一個window.name屬性值。即只要當前窗口不關閉,無論進行多少次地址跳轉,這些地址是否存在跨域都沒有關系,window.name將保存最后一次窗口的設置的值。

????????????????你也可以自行體驗一把:打開Chrome的控制臺,當前地址為:www.baidu.com。你在console的控制臺中輸入window.name='moxiao',然后將當前頁面的地址欄的地址改為:mai.qq.com,然后在console的控制臺中打印window.name將會顯示:‘moxiao’

? ? ? ? ? ? ? ? window.name的值可以在多個跨域地址中持久化,這也就是跨域父子窗口可以進行消息傳遞的基石。但是window.name屬性的設置和獲取是不能跨域進行操作的。如果父窗口想設置子窗口的window.name的屬性值,必須在同一個域下。父窗口向獲取子窗口的window.name的屬性值,也必須在同一個域名下。

? ? ? ? ? ? ? ? 當知道window.name屬性可以在多個頁面之間進行持久化的這個機制后,我們就會想象一下如何進行跨域的父子窗口傳遞消息。

? ? ? ? ? ? ? ? 當父窗口想向子窗口傳遞消息時:我們在父窗口的項目中添加一個代理頁面(proxy.html),因為父窗口和代理頁面在同一個項目下,所以不存在跨域的問題,這時候就可以在父窗口對代理窗口的window.name設置要傳遞的消息內容,設置完成之后,讓代理頁面進行window.location跳轉到子窗口中,因為是同一個窗口,所以window.name屬性將會持久化到子窗口中。這樣就可以在子窗口獲取當前窗口的window.name屬性值,也就是父窗口想要傳遞的消息。

? ? ? ? 3.2. window.name的演示示例

??https://github.com/1997chang/iframeCrossAccess中static下的name文件夾下。啟動項目之后,在地址欄中訪問:http://father.moxiao.com:8081/name/fatherName.html地址,就可以看到父窗口向子窗口發送的”moxiao“的消息內容了。

? ? 4.使用hashtag的方式(☆☆☆

? ? ? ? 4.1. hashtag介紹以及原理

? ? ? ? ? ? ? ? hashtag是地址欄中#之后的部分。注意:hash是地址欄的最后一部分。地址欄中傳遞的參數必須在#之前,否則會將他們當成是hashtag的一部分,而不是傳遞的參數了。

? ? ? ? ? ? ? ? hashtag的一個顯著的特征就是:hashtag的改變不會對頁面進行重新加載。即不會發送一個HTTP請求。當我們在地址欄中輸入一個地址時,會向服務器發送HTTP請求。當改變地址欄傳遞的參數時(?后面的參數),會重新發送HTTP請求。但是設置或者改變hashtag不會重新發送HTTP請求。給人直觀的印象就是地址欄中的地址改變了,然后就沒有任何其他的操作了。

? ? ? ? ? ? ? ? 可以使用window.location.hash的方式獲取。注意:獲取到的hash值是包含#號的。

? ? ? ? ? ? ? ? 可以使用window.onhashchange事件監聽hash值的改變。

? ? ? ? 4.2. hashtag的演示示例

??????????https://github.com/1997chang/iframeCrossAccess中static下的hash文件夾下。啟動項目之后,在地址欄中訪問:http://father.moxiao.com:8081/hash/fatherHash.html地址,就可以通過父窗口向子窗口發送消息了。

? ? ? ? 并且點擊發送按鈕,不會進行任何的頁面刷新,重新加載、發送HTTP請求什么的

四、總結?

? ? ? ? 本篇文章主要介紹父子頁面DOM操作造成的跨域問題,講述了四種解決方法。其中第一種和第二種方法最為常見。最后再考慮使用window.name和hashtag的方式進行消息的傳遞。

? ? ? ? 四種方法的項目地址為:https://github.com/1997chang/iframeCrossAccess

總結

以上是生活随笔為你收集整理的Iframe中跨域进行父子窗口进行通信的四种方法的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。