javascript動態插入技術

來源:互聯網
上載者:User

最近發現各大類庫都能利用div.innerHTML=HTML片斷來產生節點元素,再把它們插入到目標元素的各個位置上。這東西實際上就是insertAdjacentHTML,但是IE可惡的innerHTML把這優勢變成劣勢。首先innerHTML會把裡面的某些位置的空白去掉,見下面運行框的結果:

 
<!doctype html>
<html dir="ltr" lang="zh-CN">
    <head>
        <meta charset="utf-8" />
        <title>
            IE的innerHTML By 司徒正美
        </title>
        <script type="text/javascript">
            window.onload = function() {
                var div = document.createElement("div");
                div.innerHTML = "   <td>    <b>司徒</b>正美         </td>        "
                alert("|" + div.innerHTML + "|");
                var c = div.childNodes;
                alert("產生的節點個數  " + c.length);
                for(var i=0,n=c.length;i<n;i++){
                      alert(c[i].nodeType);
                      if(c[i].nodeType === 1){
                          alert(":: "+c[i].childNodes.length);
                      }
                }       
            }
        </script>
    </head>
   
    <body>
        <p id="p">
        </p>
    </body>

</html>
 
運行代碼

另一個可惡的地方是,在IE中以下元素的innerHTML是唯讀:col、 colgroup、frameset、html、 head、style、table、tbody、 tfoot、 thead、title 與 tr。為了收拾它們,Ext特意弄了個insertIntoTable。insertIntoTable就是利用DOM的insertBefore與appendChild來添加,情況基本同jQuery。不過jQuery是完全依賴這兩個方法,Ext還使用了insertAdjacentHTML。為了提高效率,所有類庫都不約而同地使用了文檔片段。基本流程都是通過div.innerHTML提取出節點,然後轉移到文檔片段上,然後用insertBefore與appendChild插入節點。對於Firefox,Ext還使用了createContextualFragment解析文本,直接插入其目標位置上。顯然,Ext的比jQuery是快許多的。不過jQuery的插入的不單是HTML片斷,還有各種節點與jQuery對象。下面重溫一下jQuery的工作流程吧。

show sourceview sourceprint?append: function() { 

  //傳入arguments對象,true為要對錶格進行特殊處理,回呼函數 

  return this.domManip(arguments, true, function(elem){ 

    if (this.nodeType == 1) 

      this.appendChild( elem ); 

  }); 

}, 

domManip: function( args, table, callback ) { 

  if ( this[0] ) {//如果存在元素節點 

    var fragment = (this[0].ownerDocument || this[0]).createDocumentFragment(), 

    //注意這裡是傳入三個參數 

    scripts = jQuery.clean( args, (this[0].ownerDocument || this[0]), fragment ), 

    first = fragment.firstChild; 

 

    if ( first ) 

      for ( var i = 0, l = this.length; i < l; i++ ) 

        callback.call( root(this[i], first), this.length > 1 || i > 0 ? 

      fragment.cloneNode(true) : fragment ); 

 

    if ( scripts ) 

      jQuery.each( scripts, evalScript ); 

  } 

 

  return this; 

 

  function root( elem, cur ) { 

    return table && jQuery.nodeName(elem, "table") && jQuery.nodeName(cur, "tr") ? 

      (elem.getElementsByTagName("tbody")[0] || 

      elem.appendChild(elem.ownerDocument.createElement("tbody"))) : 

      elem; 

  } 

//elems為arguments對象,context為document對象,fragment為空白的文檔片段 

clean: function( elems, context, fragment ) { 

  context = context || document; 

 

  // !context.createElement fails in IE with an error but returns typeof object 

  if ( typeof context.createElement === "undefined" ) 

  //確保context為文檔對象 

    context = context.ownerDocument || context[0] && context[0].ownerDocument || document; 

 

  // If a single string is passed in and its a single tag 

  // just do a createElement and skip the rest 

  //如果文檔對象裡面只有一個標籤,如<div> 

  //我們大概可能是在外面這樣調用它$(this).append("<div>") 

  //這時就直接把它裡面的元素名取出來,用document.createElement("div")建立後放進數組返回 

  if ( !fragment && elems.length === 1 && typeof elems[0] === "string" ) { 

    var match = /^<(w+)s*/?>$/.exec(elems[0]); 

    if ( match ) 

      return [ context.createElement( match[1] ) ]; 

  } 

  //利用一個div的innerHTML建立眾節點 

  var ret = [], scripts = [], div = context.createElement("div"); 

  //如果我們是在外面這樣添加$(this).append("<td>表格1</td>","<td>表格1</td>","<td>表格1</td>") 

  //jQuery.each按它的第四種支分方式(沒有參數,有length)遍曆aguments對象,callback.call( value, i, value ) 

  jQuery.each(elems, function(i, elem){//i為索引,elem為arguments對象裡的元素 

    if ( typeof elem === "number" ) 

      elem += ; 

 

    if ( !elem ) 

      return; 

 

    // Convert html string into DOM nodes 

    if ( typeof elem === "string" ) { 

      // Fix "XHTML"-style tags in all browsers 

      elem = elem.repl

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.