jQuery源码分析之buildFragment方法和clone方法

buildFragment方法源码:

var rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi;
var strundefined=undefined;
var rtagName = /<([\w:]+)/;
var rtbody = /", "" ],
		legend: [ 1, "
", "
" ], area: [ 1, "", "" ], param: [ 1, "", "" ], thead: [ 1, "", "
" ], tr: [ 2, "", "
" ], col: [ 2, "", "
" ], td: [ 3, "", "
" ], // IE6-8 can't serialize link, script, style, or any html5 (NoScope) tags, // unless wrapped in a div with non-breaking characters in front of it. _default: support.htmlSerialize ? [ 0, "", "" ] : [ 1, "X
", "
" ] } //domManip调用方式:fragment = jQuery.buildFragment( args, this[ 0 ].ownerDocument, false, this ); function buildFragment1( elems, context, scripts, selection ) { var j, elem, contains, tmp, tag, tbody, wrap, l = elems.length, // Ensure a safe fragment safe = createSafeFragment( context ), nodes = [], i = 0; //循环elems对象 for ( ; i < l; i++ ) { elem = elems[ i ]; //如果elem存在或者elem是0 if ( elem || elem === 0 ) { // Add nodes directly //如果是object那么直接放入nodes对象里面,以后直接添加到documentFragment中! if ( jQuery.type( elem ) === "object" ) { jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem ); // Convert non-html into a text node //rhtml = /<|&#?\w+;/ //把非html的内容转化为文本节点,也就是不是html标签,html标签要么开头是<要么开头是"&",构建文本节点! } else if ( !rhtml.test( elem ) ) { nodes.push( context.createTextNode( elem ) ); // Convert html into DOM nodes } else { //把html变成DOM节点,添加到safe的documentFragment上,这里是空元素! tmp = tmp || safe.appendChild( context.createElement("div") ); // Deserialize a standard representation //rtagName = /<([\w:]+)/获取标签名称 tag = (rtagName.exec( elem ) || [ "", "" ])[ 1 ].toLowerCase(); //打印[div,span] //alert(tag); //如果标签是options等标签 wrap = wrapMap[ tag ] || wrapMap._default; //[0,,][0,,] //alert(wrap) //为元素添加内容 //rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi //
'.replace( rxhtmlTag, '<$1>' );输出 tmp.innerHTML = wrap[1] + elem.replace( rxhtmlTag, "<$1>" ) + wrap[2]; //打印[
] [] // alert(tmp.innerHTML) // Descend through wrappers to the right content j = wrap[0]; //打印0,因为不再wrapMap中间 //alert(j); //获取数组第一个元素,移动到添加内容的部分 while ( j-- ) { tmp = tmp.lastChild; } // Manually add leading whitespace removed by IE //手动添加被IE移除的开头的空白节点 if ( !support.leadingWhitespace && rleadingWhitespace.test( elem ) ) { nodes.push( context.createTextNode( rleadingWhitespace.exec( elem )[0] ) ); } // Remove IE's autoinserted from table fragments //异常IE自动为table添加的tbody标签 if ( !support.tbody ) { // String was a , *may* have spurious //rtbody = / or //自己传入的是thread标签,
是自动被包裹上去的!但是elem没有tbody标签 wrap[1] === "
" && !rtbody.test( elem ) ? tmp : 0; j = elem && elem.childNodes.length; while ( j-- ) { //移除tbody标签,如果是自己传递的参数是table标签,因为wrapMap没有table标签,那么就从table开始遍历寻找tbody,如果是自己传递的thead标签 //通过上面的while循环temp也已经是jQuery自己添加的table标签了,于是从从temp也就是自己的添加的table开始就可以了! if ( jQuery.nodeName( (tbody = elem.childNodes[j]), "tbody" ) && !tbody.childNodes.length ) { elem.removeChild( tbody ); } } } //打印[object HTMLDivElement][object HTMLSpanElement]把我传入的div,和span封装到上面的空对象tmp里面 //alert(tmp.childNodes[0]); //把temp下的childNodes全部合并 jQuery.merge( nodes, tmp.childNodes ); //已经添加过了,那上面的tmp清空 // Fix #12392 for WebKit and IE > 9 tmp.textContent = ""; //在IE下进行清空 // Fix #12392 for oldIE while ( tmp.firstChild ) { tmp.removeChild( tmp.firstChild ); } // Remember the top-level container for proper cleanup //记住最外层的容器的属性,形成
tmp = safe.lastChild; //[object HTMLDivElement],[object HTMLDivElement] //alert(tmp.outerHTML); }//End of else }//End of if }//End of for // Fix #11356: Clear elements from fragment //最后一次保存了tmp,要清除,也就是这个documentFragment中作为工具的那个div //也就是最外层的div可以被删除了 if ( tmp ) { safe.removeChild( tmp ); } // Reset defaultChecked for any radios and checkboxes // about to be appended to the DOM in IE 6/7 (#8060) if ( !support.appendChecked ) { jQuery.grep( getAll( nodes, "input" ), fixDefaultChecked ); } i = 0; while ( (elem = nodes[ i++ ]) ) { // #4087 - If origin and destination elements are the same, and this is // that element, do not do anything //如果传入了第四个参数,同时elem也在第四个参数里面,那么什么也不做!如domManip函数里面传入this //也就是调用对象,所以说如果传入的对象已经在调用对象里面,那么什么也不做,见下面的例子: if ( selection && jQuery.inArray( elem, selection ) !== -1 ) { continue; } //创建的Element对象的document是否包括该元素! contains = jQuery.contains( elem.ownerDocument, elem ); //打印false // alert(contains); // Append to fragment //把创建的DOM对象放在fragment上面,同时找到这个DOM元素上面的所有的script标签! tmp = getAll( safe.appendChild( elem ), "script" ); //如果这个创建的DOM对象在当前的document上面,那么在全局作用域里面执行JS代码,如果是通过标签建立的DOM那么这里是false // Preserve script evaluation history if ( contains ) { setGlobalEval( tmp ); } //如果调用buildFragment时候传入了script是集合那么把该DOM元素上的script添加进去! //在parseHTML方法中调用是: jQuery.buildFragment( [ data ], context, scripts );这里面的script可以是数组 // Capture executables if ( scripts ) { j = 0; while ( (elem = tmp[ j++ ]) ) { //获取该创建的DOM对象的所有的script标签进行遍历!如果type是ecmascript或者javascript if ( rscriptType.test( elem.type || "" ) ) { //把这个创建的元素对象的script放入传入的第三个参数scripts集合中 scripts.push( elem ); } } } } tmp = null; //把添加的safe返回,是documentFragment对象 return safe; } buildFragment1(["

你可能感兴趣的:(jQuery源码分析之buildFragment方法和clone方法)