您的位置:首页 > Web前端 > JQuery

分析jQuery的内部插入方法

2010-09-16 09:18 369 查看
  首先,我们来看一下内部插入部分,内部插入包括append、appendTo、prepend、prependTo,对于append和prepend,jQuery内部实现比较简单,调用了JS的dom.appendChild和dom.insertBefore方法,但是在此之前调用了一个domManip的方法,domManip具体是做什么的呢?

append: function() {
return this.domManip(arguments, true, function( elem ) {
if ( this.nodeType === 1 ) {
this.appendChild( elem );
}
});
},
prepend: function() {
return this.domManip(arguments, true, function( elem ) {
if ( this.nodeType === 1 ) {
this.insertBefore( elem, this.firstChild );
}
});
},


domManip在这里可以理解为是jQuery.fn.each,与其不同的几处有:

第一个参数可以传入一个回调函数,使之返回一群jQuery元素。

若元素是一个table但没有tbody,就将tbody自动加上。

其操作会创建一个DOM文档片段,但其具体操作,还不是很清楚,以后再研究

domManip: function( args, table, callback ) {
var results, first, value = args[0], scripts = [], fragment, parent;
// We can't cloneNode fragments that contain checked, in WebKit
if ( !jQuery.support.checkClone && arguments.length === 3 && typeof value === "string" && rchecked.test( value ) ) {
return this.each(function() {
jQuery(this).domManip( args, table, callback, true );
});
}
if ( jQuery.isFunction(value) ) {
return this.each(function(i) {
var self = jQuery(this);
args[0] = value.call(this, i, table ? self.html() : undefined);
self.domManip( args, table, callback );
});
}
if ( this[0] ) {
parent = value && value.parentNode;
// If we're in a fragment, just use that instead of building a new one
if ( jQuery.support.parentNode && parent && parent.nodeType === 11 && parent.childNodes.length === this.length ) {
results = { fragment: parent };
} else {
results = buildFragment( args, this, scripts );
}

fragment = results.fragment;

if ( fragment.childNodes.length === 1 ) {
first = fragment = fragment.firstChild;
} else {
first = fragment.firstChild;
}
if ( first ) {
table = table && jQuery.nodeName( first, "tr" );
for ( var i = 0, l = this.length; i < l; i++ ) {
callback.call(
table ?
root(this[i], first) :
this[i],
i > 0 || results.cacheable || this.length > 1  ?
fragment.cloneNode(true) :
fragment
);
}
}
if ( scripts.length ) {
jQuery.each( scripts, evalScript );
}
}
return this;
function root( elem, cur ) {
return jQuery.nodeName(elem, "table") ?
(elem.getElementsByTagName("tbody")[0] ||
elem.appendChild(elem.ownerDocument.createElement("tbody"))) :
elem;
}
}


  对于appendTo、prependTo、insertBefore、insertAfter、replaceAll,
  首先jQuery做了一个hashmap,对应其内部实现的方法,然后,对jQuery中的DOM对象进行遍历,再执行其对应的方法

jQuery.each({
appendTo: "append",
prependTo: "prepend",
insertBefore: "before",
insertAfter: "after",
replaceAll: "replaceWith"
}, function( name, original ) {
jQuery.fn[ name ] = function( selector ) {
var ret = [], insert = jQuery( selector ),
parent = this.length === 1 && this[0].parentNode;

if ( parent && parent.nodeType === 11 && parent.childNodes.length === 1 && insert.length === 1 ) {
insert[ original ]( this[0] );
return this;

} else {
for ( var i = 0, l = insert.length; i < l; i++ ) {
var elems = (i > 0 ? this.clone(true) : this).get();
jQuery.fn[ original ].apply( jQuery(insert[i]), elems );
ret = ret.concat( elems );
}

return this.pushStack( ret, name, insert.selector );
}
};
});
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: