2025-02-10

 

在讀下面代碼時,我們會發現這幾個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" "https://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" "https://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

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *