IE6的base標籤導致頁面結構大混亂

來源:互聯網
上載者:User

這是一個非常隱秘也是非常強大的bug,我真不知微軟的IE開發人員是怎麼搞出來的。此bug的觸發條件是,當頁面存在一個自閉合的base節點,它就會把其“下面”所有的元素都拷到它內部。這裡的下面非childNodes,children所能描述,它連body節點都能編入其中。

<!doctype html><html>  <head>    <meta charset="utf-8"/>    <meta content="IE=8" http-equiv="X-UA-Compatible"/>    <meta name="keywords" content="IE6 base bug" />    <base href='http://www.cnblogs.com/rubylouvre/' />    <script type="text/javascript" id="test">      //http://blog.sina.com.cn/situdesign      window.onload = function(){        var meta = document.createElement("meta");        meta.name = "description";        meta.content = "IE6 base bug by 司徒正美"        var head = document.documentElement.firstChild;        head.appendChild(meta);        alert("meta.parentNode : "+meta.parentNode.tagName);        var base = document.getElementsByTagName("base")[0];        alert("base.childNodes.length : "+base.childNodes.length)        alert("body.parentNode : "+document.body.parentNode.tagName)        var script = document.getElementById("test");        alert("script.parentNode : "+script.parentNode.tagName)      }    </script>    <title>IE 複製節點 bug</title>  </head>  <body>    <h1>請在IE6下運行</h1>    <script type='text/javascript'    src='http://getfirebug.com/releases/lite/1.2/firebug-lite-compressed.js'></script>  </body></html>

<br /><!doctype html><br /><html><br /> <head><br /> <meta charset="utf-8"/><br /> <meta content="IE=8" http-equiv="X-UA-Compatible"/><br /> <meta name="keywords" content="IE6 base bug" /><br /> <base href='http://www.cnblogs.com/rubylouvre/' /><br /> <script type="text/javascript" id="test"></p><p> window.onload = function(){<br /> var meta = document.createElement("meta");<br /> meta.name = "description";<br /> meta.content = "IE6 base bug by 司徒正美"<br /> var head = document.documentElement.firstChild;<br /> head.appendChild(meta);<br /> alert("meta.parentNode : "+meta.parentNode.tagName);<br /> var base = document.getElementsByTagName("base")[0];<br /> alert("base.childNodes.length : "+base.childNodes.length)<br /> alert("body.parentNode : "+document.body.parentNode.tagName)<br /> var script = document.getElementById("test");<br /> alert("script.parentNode : "+script.parentNode.tagName)<br /> }<br /> </script><br /> <title>IE 複製節點 bug</title><br /> </head><br /> <body><br /> <h1>請在IE6下運行</h1><br /> <script type='text/javascript'<br /> src='http://getfirebug.com/releases/lite/1.2/firebug-lite-compressed.js'></script><br /> </body></p><p></html><br />

運行代碼

運行代碼下,我們發現完全亂套了,原本父節點為head的meta元素(動態產生)與父節點為html的body元素(原來就存在),它們的父節點都變成base節點。下面是用firebug lite截到的圖:

jQuery在使用globalEval方法動態解析指令碼時,就遇到這個問題,它取巧地把動態產生的script節點插入到base節點之前。

        globalEval: function( data ) {            if ( data && rnotwhite.test(data) ) {                var head = document.getElementsByTagName("head")[0] || document.documentElement,                script = document.createElement("script");                script.type = "text/javascript";                if ( jQuery.support.scriptEval ) {                    script.appendChild( document.createTextNode( data ) );                } else {                    script.text = data;                }                head.insertBefore( script, head.firstChild );                head.removeChild( script );            }        },

但還是不妥當,因為始終留著個陷阱給人踩。想了想,base標籤無礙乎只有兩個屬性,用於對頁面上所有的URL進行統一設定,如img.src,form.action,a.href等等。通常只有一個就夠了,如果它只存在於body中,不管,如果存在於head就會為害人間了,我們需要將它強制添加一個閉合標籤。即,將它由

 <base href='http://www.cnblogs.com/rubylouvre/' />

轉換為

 <base href='http://www.cnblogs.com/rubylouvre/' ></base>

雖然IE6解析base的半閉合形式出錯,但它不會不濟到解析一個全新的節點出錯吧,它理應會把新節點轉換為它不會出錯的形式,換言之,是第二種形式。建立新節點的方法有許多種,但我們很需要原節點的屬性,恰好IE的cloneNode什麼也能複製。之後就是插入節點的問題了,我們使用它的一個私人實現replaceNode,不用知曉其父節點,它也將用於區分IE與非IE。

下面是我的fixbug程式:

//by 司徒正美//此bug在IE7中修複,詳見://http://blogs.msdn.com/ie/archive/2005/08/29/457667.aspx        if(document.replaceNode && !window.XMLHttpRequest){          var head = document.getElementsByTagName("head")[0],          base = head.getElementsByTagName("base")[0],          headFrag = document.createDocumentFragment(),          bodyFrag = headFrag.cloneNode(),el;           if(base && base.childNodes.length){            for (; el =base.childNodes[0];) {              if(el.tagName === "BODY"){                bodyFrag.appendChild(el);                break;              }else{                headFrag.appendChild(el)              }            }            base.replaceNode(base.cloneNode())            head.appendChild(headFrag);            document.documentElement.appendChild(bodyFrag)          }        }

<br /><!doctype html><br /><html><br /> <head><br /> <meta charset="utf-8"/><br /> <meta content="IE=8" http-equiv="X-UA-Compatible"/><br /> <meta name="keywords" content="IE6 base bug" /><br /> <base href='http://www.cnblogs.com/rubylouvre/' /><br /> <script type="text/javascript" id="test"></p><p> window.onload = function(){<br /> if(document.replaceNode && !window.XMLHttpRequest){<br /> var head = document.getElementsByTagName("head")[0],<br /> base = head.getElementsByTagName("base")[0],<br /> headFrag = document.createDocumentFragment(),<br /> bodyFrag = headFrag.cloneNode(),el;<br /> if(base && base.childNodes.length){<br /> for (; el =base.childNodes[0];) {<br /> if(el.tagName === "BODY"){<br /> bodyFrag.appendChild(el); break;<br /> }else{<br /> headFrag.appendChild(el)<br /> }<br /> }<br /> base.replaceNode(base.cloneNode())<br /> head.appendChild(headFrag);<br /> document.documentElement.appendChild(bodyFrag)<br /> }<br /> }<br /> // =================測試代碼==========<br /> var meta = document.createElement("meta");<br /> meta.name = "description";<br /> meta.content = "IE6 base bug by 司徒正美"<br /> var head = document.documentElement.firstChild;<br /> head.appendChild(meta);<br /> alert("meta.parentNode : "+meta.parentNode.tagName);<br /> var base = document.getElementsByTagName("base")[0];<br /> alert("base.childNodes.length : "+base.childNodes.length)<br /> alert("body.parentNode : "+document.body.parentNode.tagName)<br /> var script = document.getElementById("test");<br /> alert("script.parentNode : "+script.parentNode.tagName)<br /> }<br /> </script><br /> <title>IE 複製節點 bug</title><br /> </head><br /> <body><br /> <h1>請在IE6下運行</h1><br /> <script type='text/javascript'<br /> src='http://getfirebug.com/releases/lite/1.2/firebug-lite-compressed.js'></script><br /> </body></p><p></html><br />

運行代碼

搞定!不過,我的globalEval函數用不著這個,直接用execScript一了百了,連script標籤也不用插入。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.