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