• IE6的base标签导致页面结构大混乱


    这是一个非常隐秘也是非常强大的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>
    

    运行代码下,我们发现完全乱套了,原本父节点为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)
              }
            }
    

    搞定!不过,我的globalEval函数用不着这个,直接用execScript一了百了,连script标签也不用插入。

  • 相关阅读:
    什么是Redis?简述它的优缺点?
    2021年最新盘点数据库MySql笔试题
    网易CTO:70%.NET开发,遇到这个问题就怂!
    近200篇机器学习&深度学习资料分享【转载】
    【转】为什么0.1无法被二进制小数精确表示?
    【Leetcode-easy】Remove Element
    【Leetcode-easy】Remove Duplicates from Sorted Array
    【LeetCode-easy】Merge Two Sorted Lists
    【Leetcode-easy】Valid Parentheses
    【Leetcode-easy】Remove Nth Node From End of List
  • 原文地址:https://www.cnblogs.com/rubylouvre/p/1738034.html
Copyright © 2020-2023  润新知