jQuery3.0的buildFragment

在 jQuery3.0中,buildFragment 是一个私有函数,用来构建一个包含子节点 fragment 对象。这个 fragment 在 DOM1 中就已经有了,所有浏览器都支持。当频繁操作(添加、插入) DOM 时使用该方法可以提高性能,John resig 做过一个测试及一篇博客

jQuery3.0 中 buildFragment 只在 domManip 和 jQuery.parseHTML 中使用,domManip 则被 DOM 操作如 append、prepend、before、after 等方法的所依赖。如下图

buildFragment 函数有 5 个参数,源码如下

function buildFragment( elems, context, scripts, selection, ignored ) {
	var elem, tmp, tag, wrap, contains, j,
		fragment = context.createDocumentFragment(),
		nodes = [],
		i = 0,
		l = elems.length;

	for ( ; i < l; i++ ) {
		elem = elems[ i ];

		if ( elem || elem === 0 ) {

			// Add nodes directly
			if ( jQuery.type( elem ) === "object" ) {

				// Support: Android <=4.0 only, PhantomJS 1 only
				// push.apply(_, arraylike) throws on ancient WebKit
				jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem );

			// Convert non-html into a text node
			} else if ( !rhtml.test( elem ) ) {
				nodes.push( context.createTextNode( elem ) );

			// Convert html into DOM nodes
			} else {
				tmp = tmp || fragment.appendChild( context.createElement( "div" ) );

				// Deserialize a standard representation
				tag = ( rtagName.exec( elem ) || [ "", "" ] )[ 1 ].toLowerCase();
				wrap = wrapMap[ tag ] || wrapMap._default;
				tmp.innerHTML = wrap[ 1 ] + jQuery.htmlPrefilter( elem ) + wrap[ 2 ];

				// Descend through wrappers to the right content
				j = wrap[ 0 ];
				while ( j-- ) {
					tmp = tmp.lastChild;
				}

				// Support: Android <=4.0 only, PhantomJS 1 only
				// push.apply(_, arraylike) throws on ancient WebKit
				jQuery.merge( nodes, tmp.childNodes );

				// Remember the top-level container
				tmp = fragment.firstChild;

				// Ensure the created nodes are orphaned (#12392)
				tmp.textContent = "";
			}
		}
	}

	// Remove wrapper from fragment
	fragment.textContent = "";

	i = 0;
	while ( ( elem = nodes[ i++ ] ) ) {

		// Skip elements already in the context collection (trac-4087)
		if ( selection && jQuery.inArray( elem, selection ) > -1 ) {
			if ( ignored ) {
				ignored.push( elem );
			}
			continue;
		}

		contains = jQuery.contains( elem.ownerDocument, elem );

		// Append to fragment
		tmp = getAll( fragment.appendChild( elem ), "script" );

		// Preserve script evaluation history
		if ( contains ) {
			setGlobalEval( tmp );
		}

		// Capture executables
		if ( scripts ) {
			j = 0;
			while ( ( elem = tmp[ j++ ] ) ) {
				if ( rscriptType.test( elem.type || "" ) ) {
					scripts.push( elem );
				}
			}
		}
	}

	return fragment;
}

该方法主要执行步骤

  1. 通过第二个参数 content 创建 fragment
  2. 通过第一个参数 elems 构建 nodes ,将 elems 内元素转成 DOM 元素存放于数组 nodes 中
  3. 将 nodes 里元素循环放入添加到文档碎片 fragment 上
  4. 返回 fragment

重点在第 2 步,构建 nodes,有 3 种情形

  1. elem 是 DOM 元素(根据nodeType判断),直接放入 nodes 数组中
  2. elem 是字符串且不是 HTML tag,创建文本节点对象(textNode),放入 nodes 数组中
  3. elem 是字符串且是 HTML tag,将其转成 DOM 元素,放入 nodes 数组中

如图示

后面的两个参数需要注意下

1. 最后两个参数 selection 和 ignored 只在 replaceWith 方法里使用。需要了解的是 replaceWith 只做节点替换,不会替换先前元素的所有数据(Data),比如绑定事件,$.data 都不会被新元素拥有。

2. scripts 参数只在 jQuery.parseHTML 方法里使用(domManip里传false),当 jQuery.parseHTML 的第三个参数 keepScripts 为 false 时将删除节点里所有的 script tag

时间: 2024-12-20 19:48:59

jQuery3.0的buildFragment的相关文章

jQuery3.0的domManip浅析

domManip 这个函数的历史由来已久,从 jQuery 1.0 版本开始便存在了,一直到最新的 jQuery 版本.可谓是元老级工具函数. domManip 的主要功能是为了实现 DOM 的插入和替换.具体共为以下 5 个函数服务 内部后插入(append) 内部前插入(prepend) 外部前插入(before) 外部后插入(after) 替换元素 (replaceWith,1.9.x 之前的版本没有使用 domMainp) 而一个 each 就生成了另外 5 个函数:appendTo.p

Jqury元素.get(0)转换为JavaScript元素 -时间倒计时

html+css布局: <!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title> 倒计时2</title> <style> /* reset css 样式重置 */ body,p,pre,h1,h2,h3,h4,h5,h6,ul,ol,li,dl,dt,dd,table,tr,td,div,img,f

PJax在jQuery 3.0无法运行问题修复

PJax在jQuery 3.0无法运行 [现象] 页面报错:Uncaught TypeError: Cannot read property 'push' of undefined [原因] jQuery3.0开始去除了$.event.props Breaking change: jQuery.event.props and jQuery.event.fixHooks removed jQuery's event handling performance increased thanks to

jQuery 3.0 的 Data 浅析

jQuery 3.0 在6月9日正式发布了,3.0 也被称为下一代的 jQuery .这个版本从14年10月开始,其中发布过一次beta 版(2016/1/14,)和候选版(2016/05/20).一路走来,颇为不易. 文章目录 Data浅析 Data在jQuery内部的使用 1.x.x 和 2.x.x 的比较 一.Data浅析 jQuery 3.0 中的 Data 是内部使用的,定义为一个“类”.一共用它创建了两个对象,dataPriv 和 dataUser.Data 有 1 个对象属性(ex

jQuery 3.0 的 Data

jQuery 3.0 的 Data Snandy If you cannot hear the sound of the genuine in you, you will all of your life spend your days on the ends of strings that somebody else pulls. jQuery 3.0 的 Data 浅析 jQuery 3.0 在6月9日正式发布了,3.0 也被称为下一代的 jQuery .这个版本从14年10月开始,其中发布

[jQuery]最新的 3.0 已发布

可以从 https://code.jquery.com/jquery/#jquery-all-1.x 找到历史版本 1.12.4 是支持 IE6 - 8 的最高版本. 下载地址 http://files.cnblogs.com/files/z5337/jquery-1.12.4.min.js http://files.cnblogs.com/files/z5337/jquery-1.12.4.js 3.0 下载地址 http://files.cnblogs.com/files/z5337/jqu

bootstrap中的对话框-dialog

<!DOCTYPE html><html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0" /> <meta http-

bootstrap中的对话框-dialog-2

<!DOCTYPE html><html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0" /> <meta http-

使用JavaScript为一张图片设置备选路径

在做网页开发的时候,有时候希望给图片设置一个备选路径,即,当src属性对应的主路径加载失败的时候,图片可以马上切换到备选路径.这样,即使主路径失效了,显示备用路径也不会影响网页的正常体验. 注意到网页中一张图片加载失败会触发error事件,因此可以使用DOM模型中的load和error事件实现这一效果. src1='main/image.jpg' //主路径 src2='another/image.jpg' //备用路径 jQuery 1.8以前 使用load和error方法捕捉事件 $('#i