• <noscript id="eom2a"><optgroup id="eom2a"></optgroup></noscript>
    <tt id="eom2a"><small id="eom2a"></small></tt>
    <input id="eom2a"></input>
  • <div id="eom2a"><small id="eom2a"></small></div>
    <td id="eom2a"><small id="eom2a"></small></td>
  • 您的位置:知識庫 ? Web前端

    iframe詭異的內容消失問題

    來源: 宅居  發布時間: 2011-01-20 23:54  閱讀: 5135 次  推薦: 0   原文鏈接   [收藏]  
    摘要:該文章講解iframe詭異的內容消失問題,希望對您有所幫助。

      問題描述

      不得不承認,這是一個非常詭異的問題,以下步驟可以重現問題:

    1. 用IE打開這個測試頁面,確認頁面上有個iframe,里面顯示著abc三個字符。
    2. 把這頁面加進收藏夾。
    3. 重新打開IE。
    4. 從收藏夾再打開這頁面 。

      如果沒出問題的話,你會發現頁面上雖然還有iframe,但是abc消失了。更準確、詳細地說,前后2次的頁面主要有以下區別:

    • 從視覺上來說,頁面中的abc字符消失了。
    • 從DOM結構上看,iframe中的body元素內沒有任何內容。
    • 從iframe的右鍵-屬性上看,第一次頁面上iframe的地址是父頁面的URL,第二次則變成了about:blank。

      以下是這個頁面的源碼,是從遇上問題的頁面中不斷分離、簡化,最后形成的一個最簡的重現方案:

    !DOCTYPE html
    html
    head
    meta charset="utf-8" /
    titletest/title
    /head
    body
    script type="text/javascript"
    var text = 'abc',
    script
    = 'var d = document; ' +
    'd.open(\'text/html\', \'replace\'); d.write(parent.text); d.close();',
    html = 'iframe id="abc" name="abc" ' +
    'src="javascript:void((function() {' + script + '})())"/iframe';
    document.write(html);
    /script
    /body
    /html

      解決方案

      首先,這個頁面雖然簡單,但其中用到了幾個很惡心人的東西:

    • document.write。
    • javascript:偽協議。

      如果有辦法避免使用這兩者的話,就可以忽略這個問題。但是如果必須使用javascript:偽協議來向iframe中輸出內容的話,將以上代碼改為如下形式可以解決問題:

    var iframe = document.createElement('iframe');
    document.body.appendChild(iframe);
    //插入到需要的位置
    iframe.contentWindow.location = 'javascript:void((function() {' + script + '})())';

      具體的區別是,從直接使用document.write來輸出iframe,變為了使用createElement創建iframe,隨后使用iframe的location來采用javascript:偽協議輸出具體內容。

      起因

      由于原本這段代碼不是我寫的,所以在發現這個問題的時候,我也有過疑問,為啥要這么寫呢?難道下面的方式不是更好嗎:

    var iframe = document.createElement('iframe');
    document.body.appendChild(iframe);
    //插入到需要的位置
    iframe.contentWindow.document.write('abc');

      然而這一段代碼的注釋中寫是IE在修改了document.domain進行提權后,iframe會出現跨域問題。所以以下代碼,其中在IE中是會報錯(拒絕訪問)的:

    //假設當前域是www.tt.com
    document.domain = 'tt.com'; //domain提權
    var iframe = document.createElement('iframe');
    document.body.appendChild(iframe);
    //插入到需要的位置
    iframe.contentWindow.document.write('abc');

      至于解決的辦法,就是在iframe的src中,使用javascript:偽協議輸出內容,當然輸出的時候要注意,在iframe的document執行open以后,加上一句代碼,把iframe的docuemnt.domain也進行提權,提升到和父頁面相同,這樣iframe和父頁面就是同域的,可以進行交互了。

      正是因為IE存在著這樣的問題,為了解決這個問題,原有代碼中使用了document.write輸出帶src屬性的iframe元素,從而引發了另一個問題&hellip;&hellip;

      猜測

      那么這個問題是因為什么原因引起的呢?首先對頁面的執行過程進行分析,大致是這么幾步:

    1. 解析script標簽,執行內容。
    2. document.write向文檔流中輸出一個iframe元素。
    3. iframe中,使用document.write輸出文字。

      從頁面的視覺效果而言,iframe是存在的,但iframe里面的內容消失了。這讓人很自然地聯想到,第2步已經執行了,但由于瀏覽器緩存iframe的內容等原因,第3步并沒有執行。

      為了測試這個情況,比較簡單的方法就是在iframe的src里的javascript代碼中添加一個斷點,我的選擇是在d.close()這一句之前,加上了一行代碼:alert(d.body.innerHTML);

      經過以上的修改,執行的結果是,成功地出現了alert對話框,并且innerHTML確實存在abc字符,另外更奇怪的是,經過alert,abc出現在了iframe中。

      也就是說,第3步是確實地執行了,但是在沒有alert的情況下,卻沒有在界面上產生任何效果。綜合以上的原因,聯想到alert函數的一個作用是將瀏覽器的UI Update隊列進行flush操作,因此對于完全黑盒的IE瀏覽器,現階段只能猜測,在這種特殊的使用方式之下,IE丟失了UI Update隊列中的部分更新,導致iframe的document并沒有得到更新,因此也保留了about:blank這種地址。

    0
    0

    Web前端熱門文章

      Web前端最新文章

        最新新聞

          熱門新聞

            黄色网_免费在线黄色电影_黄色成人快播电影_伦理电影_黄色片