精品伊人久久大香线蕉,开心久久婷婷综合中文字幕,杏田冲梨,人妻无码aⅴ不卡中文字幕

打開APP
userphoto
未登錄

開通VIP,暢享免費電子書等14項超值服

開通VIP
【翻譯】Iframe, onload 與 document.domain
原文鏈接:http://www.nczonline.net/blog/2009/09/15/iframes-onload-and-documentdomain/
譯者:Demix

在web2.0的時代,越來越多的人開始關注使用iframe將第三方網站的內容嵌入自己的網站中。當javascript能夠通過其域名進行數據交互后,iframe開始提供一系列的安全措施,使得一個嵌套于iframe中的第三方網站不可能獲取到主體網站的腳本程序。這個跨域的限制同樣也讓父級頁面無法讀取嵌套內容的腳本。從所有的角度來說,父級頁面和被iframe包含的頁面是完全沒有聯系的。這個復雜的關系讓javascript對象的所有權成為了許多有關iframe討論的話題之一。

iframe 和所有權

iframe元素本身是位于父級頁面中的,所以你可以像一個普通元素一樣的使用和操作它。代表了iframe內容window對象是作為一個頁面的屬性加入到iframe中的。為了讓父級頁面能夠以一種合適的方式獲取iframe的window對象,父級頁面和iframe頁面的域名應該保持一致(詳情)。

當域名吻合時,父級頁面就可以獲取到iframe的window對象了。iframe元素擁有名為contentDocument的屬性,這個屬性包含了iframe對象的document對象,于是我們就可以使用parentWindow這個屬性取回window對象。這已經成為了獲取iframe的window對象的標準方法,并被絕大多數瀏覽器支持。ie8以前的瀏覽器不支持這個屬性,我們需要用以使用其專有的contentWindow屬性。如

1  function  getIframeWindow(iframeElement){
2       return  iframeElement.contentWindow  ||  iframeElement.contentDocument.parentWindow;
3  }

補充一點,父級頁面的window對象在iframe中能夠以window.parent獲取。iframe元素同樣也可以使用window.frameElement來獲取自己的引用。由于iframe被父級元素包含但卻可以直接獲取到iframe的window對象,該方法廣泛用于突破二者的界限。

使用iframe元素的onload事件

由于各種所有權的不同,嘗試確定iframe何時裝載完畢是一個很有趣的實驗。非ie瀏覽器提供了許多有用的方法。它們讓iframe元素擁有load事件,這樣我們就可以確定iframe何時裝載完全。由于iframe元素包含于父級頁面中,你也不用擔心跨域的限制。裝載本地數據的iframe可以使用監聽裝載外部數據的iframe完成事件的相同方法。舉例如下:

1  var  iframe  =  document.createElement( " iframe " );
2  iframe.src  =   " simpleinner.htm " ;
3  iframe.onload  =   function (){
4      alert( " Iframe is now loaded. " );
5  };
6  document.body.appendChild(iframe);

上面的例子在所有非ie瀏覽器中均適用。我曾經嘗試使用attachEvent方法,不過最終發現ie并不支持在iframe上的load事件。

使用iframe的window對象的onload事件

看起來ie又要給我們制造難題了。不過隨后,我記起來我以前沒有考慮過在iframe中引用外部文件。在我的實驗中,我曾經處理了同一域名下的內容。由于跨域限制不存在,我能夠輕易的獲取iframe對象的window對象并加上onload事件。例如:

1  var  iframe  =  document.createElement( " iframe " ),
2      iframeWindow;
3  iframe.src  =   " simpleinner.htm " ;
4  document.body.appendChild(iframe);
5  iframeWindow  =  iframe.contentWindow  ||  iframe.contentDocument.parentWindow;
6  iframeWindow.onload  =   function (){
7      alert( " Local iframe is now loaded. " );
8  };

有趣的是,你必須在iframe元素已經加到頁面中以后才能注冊事件。如果先于它,iframe的window對象將不存在,我們也當然不可能在window對象上注冊事件。這個方法只在ie和ff下對于同域的兩個嵌套頁面有效。其他瀏覽器不會創建window對象并將拋出異常。

定義document.domain

我試圖尋找一種可以監聽ie里iframe的load事件的方法以及更多的應用于其他瀏覽器的方法,于是我繼續了我的實驗。接下來,由于我有多個需要使用iframe讀取的不同二級域名的頁面,我設置了父級頁面的document.domain。將document.domain設定為主域名能夠允許這些iframe之間以及同父級頁面的通信。例如,如果我有需要讀取一個地址為www2.nczonline.net的iframe,在技術上上說是不被允許的。不過,如果我在父級頁面和iframe頁面中均設置了document.domain為'nczonline.net',這兩個頁面將可以相互通訊。如下:

1  document.domain  =   " nczonline.net " ;

這個聲明消除了域名的區別,我們可以像處理兩個相同域名的網站一樣處理這兩個頁面。

有一個問題又產生了。在iframe完全加載前,它將被認為是屬于iframe標簽中聲明的src屬性標志的頁面的。相對地址被自動加上了父級頁面的地址(www.nczonline.net)并與我們設置的document.domain相矛盾。這意味著在比較nczonline.net和www.nczonline.net時,我們將通不過同域檢查,于是當我們試圖獲取iframe的window對象時,將引起javascript的報錯。iframe頁面并不會改變其關聯的domain值,直到它加載完畢,屆時改變domain值的腳本才會執行。當iframe已經加載完畢時,一切運行完美。但是,我們是怎么知道iframe什么時候才加載完?

換個方向思考

由于一致沒有找到一種可以跨瀏覽器解決判定iframe是否加載完畢的方法,我決定轉變一下我的想法。如果我們讓iframe告訴父級頁面它已經加載完畢,而不是讓父級頁面去獲取iframe的load事件,也許能夠解決問題。我希望這種方法能夠與注冊一個事件句柄一樣簡單,所以我采用了下面的想法:我在iframe元素上聲明一個方法,然后,當iframe頁面加載完畢之后會執行這個函數。當然,這個方法是被聲明到iframe元素本身而不是iframe的window對象上的,后一方法在前面的研究中被證明不能兼容所有的瀏覽器。結果看起來像這樣:

1  var  iframe  =  document.createElement( " iframe " );
2  iframe.src  =   " simpleinner.htm " ;
3  iframe._myMethod  =   function (){
4      alert( " Local iframe is now loaded. " );
5  };
6  document.body.appendChild(iframe);

上面的代碼在iframe元素上聲明了_myMethod的方法。iframe中的頁面加入如下方法:

1  window.onload  =   function (){
2      window.frameElement._myMethod();
3  }

由于上述代碼是在我們聲明document.domain之后運行的,于是我們便不用擔心任何安全限制的問題。這種方法在同一主域名下工作得很完美。它能夠兼容所有的瀏覽器,這也正是我所需要的。但是,監聽包含第三方頁面的iframe的load事件仍然在困擾我。

使用iframe的onreadystatechange

我決定研究一下ie瀏覽器關于iframe的接口文檔。如果在onload事件中聲明某些事件顯而易見不能達到我們想要的效果,但是我覺得肯定會有類似的方法。我嘗試使用attachEvent方法去增加事件句柄,但是仍然沒有用。ok,顯然ie中的iframe并不支持load事件。有其他方法嗎?

接下來我使用了ie的一種怪異的方法——readystatechange事件。顯然它與xhr對象的readystatechange事件完全不一樣。我想知道是否iframe元素也支持這個事件,它會在iframe嵌套的內容加載完全前變成'interactive',隨后變成'complete'。同時,由于它是注冊到iframe元素而不是iframe的window對象上,這理所當然不會存在跨域的問題。最后我整理出來的代碼如下:

 1  var  iframe  =  document.createElement( " iframe " );
 2  iframe.src  =   " simpleinner.htm " ;
 3 
 4  if  (navigator.userAgent.indexOf( " MSIE " >   - 1   &&   ! window.opera){
 5      iframe.onreadystatechange  =   function (){
 6           if  (iframe.readyState  ==   " complete " ){
 7              alert( " Local iframe is now loaded. " );
 8          }
 9      };
10  else  {
11      iframe.onload  =   function (){
12          alert( " Local iframe is now loaded. " );
13      };
14  }
15 
16  document.body.appendChild(iframe);

判斷瀏覽器是否為ie瀏覽器稍稍有些麻煩。本來我更偏向使用判斷iframe.readystate是否存在來進行瀏覽器的檢測。但是,當試圖獲取未加入到頁面中的iframe的屬性時會拋出一個錯誤。我也嘗試使用document.readyState去判斷是否使用readystatechange,然而,已經有很多瀏覽器支持前一屬性了,所以它并不是一個有效的劃分手段。

ie 對onload事件的支持

在發表這篇文章后短暫的時間里, Christopher留言說在iframe元素上使用attachEvent是能夠在ie下工作的。我發誓我之前已經嘗試過這樣的方法,但是由于他的提示,我嘗試了另外一個實驗。隨后發現,他是正確的。隨后我研讀了msdn上的文檔,最后終于發現了一段文檔說明了這個問題。它最終讓我們的代碼變成了下面這個樣子

 1  var  iframe  =  document.createElement( " iframe " );
 2  iframe.src  =   " simpleinner.htm " ;
 3 
 4  if  (iframe.attachEvent){
 5      iframe.attachEvent( " onload " function (){
 6          alert( " Local iframe is now loaded. " );
 7      });
 8  else  {
 9      iframe.onload  =   function (){
10          alert( " Local iframe is now loaded. " );
11      };
12  }
13 
14  document.body.appendChild(iframe);

以上的代碼仍然能正常運行于所有的瀏覽器之上,并能回避readystatechange事件與load事件潛在的沖突可能。

綜合

在一小段調研之后,我們發現確定一個iframe對象何時加載完成的跨瀏覽器的方法是存在的。這讓我們對iframe的監聽和錯誤控制變得容易的多。感謝所有的瀏覽器廠商看到了在iframe元素上添加這些事件的好處,而不是去依賴iframe的window對象或者認為我們平時并不關心iframe何時完成加載。


很久沒有翻譯了,草草翻譯出上面這篇文章,錯誤一定不少。Zakas這篇文章很搞笑,寫出來幾分鐘后有人留言說里面有錯誤,又改掉了。這里我們又看到寫博客的一個好處——共同成長。如果沒有后來的評論,也許Zakas會一直使用不太優雅的監聽readystatechange事件來實現。另外通過這篇文章,我們看到了大師的細致之處。雖然整篇文章所描述的問題也許我們平時都會有接觸,但是又有哪一個人會有這樣的細致。PPK也如此,老道也如此,所有的大師都是如此。成功,重在細節。
本站僅提供存儲服務,所有內容均由用戶發布,如發現有害或侵權內容,請點擊舉報
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
JS操作iframe
jquery $(document).ready() 與window.onload的區別
JS DOMReady事件的六種實現方式
YY in Limbo 混沌海狂想 ? DOM加載事件的終極解決方案
jQuery用iframe來解決跨域的簡單示例(1)
window.name實現的跨域數據傳輸
更多類似文章 >>
生活服務
分享 收藏 導長圖 關注 下載文章
綁定賬號成功
后續可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點擊這里聯系客服!

聯系客服

主站蜘蛛池模板: 时尚| 崇礼县| 明星| 都兰县| 红桥区| 昂仁县| 湘潭市| 关岭| 古浪县| 泰来县| 宿松县| 商水县| 文化| 磴口县| 汨罗市| 云龙县| 沙雅县| 基隆市| 藁城市| 磴口县| 柯坪县| 新泰市| 宁国市| 通道| 察隅县| 阿荣旗| 玉树县| 惠水县| 榕江县| 新兴县| 信阳市| 惠安县| 响水县| 乌审旗| 精河县| 萨迦县| 南雄市| 丰城市| 遂昌县| 紫云| 泌阳县|