jQuery1.0原始碼分析之domManip方法(七)

來源:互聯網
上載者:User

 

在讀下面代碼時,我們會發現這幾個Dom操作的函數都會調用domManip函數

 

append: function() { 

        return this.domManip(arguments, true, 1, function(a){ 

            this.appendChild( a ); 

        }); 

    }, 

    prepend: function() { 

        return this.domManip(arguments, true, -1, function(a){ 

            this.insertBefore( a, this.firstChild ); 

        }); 

    }, 

    before: function() { 

        return this.domManip(arguments, false, 1, function(a){ 

            this.parentNode.insertBefore( a, this ); 

        }); 

    }, 

    after: function() { 

        return this.domManip(arguments, false, -1, function(a){ 

            this.parentNode.insertBefore( a, this.nextSibling ); 

        }); 

    }, 

那這個domManip函數是幹什麼用的呢?

 

dom即Dom元素,Manip是Manipulate的縮寫,連在一起就是Dom操作的意思。

 

 

我們來看下面一段代碼,代碼本身很簡單,就是在table中插入一行一列,並寫上文本haha。

 

 

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> 

<html lang="en"> 

<head> 

    <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> 

    <title></title> 

    <script type="text/javascript"> 

    window.onload = function() { 

        var table = document.getElementsByTagName('table')[0]; 

        var tr = document.createElement('tr'); 

        var td = document.createElement('td'); 

        var txt = document.createTextNode('haha'); 

        td.appendChild(txt); 

        tr.appendChild(td); 

        table.appendChild(tr); 

    }; 

    </script> 

</head> 

<body> 

    <table></table> 

</body> 

</html> 

 

但是,上面代碼在IE 6上是執行不成功的,大家可以試一下。在IE 8以上的瀏覽器都是好用的。

 

萬惡的IE!!!!!

 

IE 6上失敗的原因就是IE 6認為tr標籤必須在tbody下面。也就是說,代碼寫成下面這樣,就所有瀏覽器都OK了。

 

 

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> 

<html lang="en"> 

<head> 

    <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> 

    <title></title> 

    <script type="text/javascript"> 

    window.onload = function() { 

        var table = document.getElementsByTagName('table')[0]; 

        var tbody = document.createElement('tbody'); 

        var tr = document.createElement('tr'); 

        var td = document.createElement('td'); 

        var txt = document.createTextNode('haha'); 

        td.appendChild(txt); 

        tr.appendChild(td); 

        tbody.appendChild(tr); 

        table.appendChild(tbody); 

    }; 

    </script> 

</head> 

<body> 

    <table></table> 

</body> 

</html> 

 

原因清楚了,我們在來看jQuery是如何處理tbody問題,jQuery是相容IE 6瀏覽器的。

 

append、prepend、before和after都是操作Dom元素的函數,如果被插入的對象是table,那就要在table中加入tbody標籤啊。

 

所以domManip,主要是處理這個問題的,他還處理插入元素的順序。我們一點一點來看代碼。

 

 

我們這裡就先那append函數來具體說明,

 

 

append: function() { 

        return this.domManip(arguments, true, 1, function(a){ 

            this.appendChild( a ); 

        }); 

    } 

這個函數調用了domManip函數,傳進去的參數第一個是arguments,這個大家都知道arguments是函數參數對象,是一個類數組對象。這裡arguments可能是包含dom元素的數組,或者html字串。

 

第二個參數true,要處理tbody情況。因為當前jQuery執行個體對象是一個table元素,append一個tr元素,就會有tbody的情況,所以需要處理。像後面的before和after函數就不需要,因為他們是再外部追加元素。

 

第三個參數1,代表方向,1代表正向,從上到下,-1代表反向,從下到上。你可以想象一下,如果prepend一大堆dom元素,那一定先prepend一大堆dom元素中的最後一個,然後是倒數第二個,依此類推,一直到第一個。要不然你prepend以後的dom元素是反向的。

 

第四格參數是function,裡面調用的appendChild方法來append元素,底層還是要調用w3c dom函數的。

 

通過上面講解,我們就明白了append的大致參數的意思了,我們再來對照看一下domManip,就都明白了。

 

 

domManip: function(args, table, dir, fn){ 

        var clone = this.size() > 1; 

        var a = jQuery.clean(args); 

         

        return this.each(function(){ 

            var obj = this; 

             

            if ( table && this.nodeName == "TABLE" && a[0].nodeName != "THEAD" ) { 

                var tbody = this.getElementsByTagName("tbody"); 

 

                if ( !tbody.length ) { 

                    obj = document.createElement("tbody"); 

                    this.appendChild( obj ); 

                } else 

                    obj = tbody[0]; 

            } 

 

            for ( var i = ( dir < 0 ? a.length - 1 : 0 ); 

                i != ( dir < 0 ? dir : a.length ); i += dir ) { 

                    fn.apply( obj, [ clone ? a[i].cloneNode(true) : a[i] ] ); 

            } 

        }); 

    }, 

clone表示的是當你的jQuery執行個體對象是好幾個的時候,就需要cloneNode。原因很簡單,你jQuery執行個體對象是一個元素的時候,你append一下就沒問題了。但是你jQuery執行個體對象多個元素的時候,你把args append到第一個元素上了,jQuery執行個體的第二個元素他怎麼辦啊?他沒有可以append的了?!所以,上來要判斷一下size是不是大於1,大於1就需要cloneNode。

 

 

var obj = this; 

這個obj是jQuery對象執行個體中的一個元素。

 

 

if ( table && this.nodeName == "TABLE" && a[0].nodeName != "THEAD" ) { 

    var tbody = this.getElementsByTagName("tbody"); 

 

    if ( !tbody.length ) { 

        obj = document.createElement("tbody"); 

        this.appendChild( obj ); 

    } else 

        obj = tbody[0]; 

這一段就是給table元素加tbody,如果沒有的話,然後將obj指到tbody上

 

 

 

for ( var i = ( dir < 0 ? a.length - 1 : 0 ); 

    i != ( dir < 0 ? dir : a.length ); i += dir ) { 

        fn.apply( obj, [ clone ? a[i].cloneNode(true) : a[i] ] ); 

這一段代碼很多人看不明白,其實就是append的順序,有的時候,需要從最後一個元素開始prepend。

 

 

到這裡我相信domManip函數的意義,大家就明白了吧

作者 baozhifei

聯繫我們

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