分析jQuery的内部插入方法

  首先,我们来看一下内部插入部分,内部插入包括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,与其不同的几处有:

  1. 第一个参数可以传入一个回调函数,使之返回一群jQuery元素。
  2. 若元素是一个table但没有tbody,就将tbody自动加上。
  3. 其操作会创建一个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 ); } }; });

你可能感兴趣的:(jquery)