jQuery源码研究:选择器

版权声明:本文为微信公众号前端小二版权所有,如需转载可私信或关注微信公众号留言。 https://blog.csdn.net/qq_34832846/article/details/86298051

jQuery的css选择器,是一大亮点,其实现源码也可单独拎出来作为模块使用。

先看个整体,在jQuery源码中在行229-2752区域。

var Sizzle = (function(window){
    // 具体实现暂略...
})(window)

css选择器的具体实现是一个匿名自执行函数,传入参数为window对象。函数顶部定义若干变量,包括本地文档变量、特定实例数据和特定实例方法,此外还定义了一些为选择器字符串服务的正则表达式。数量太多就不一一列举了,感兴趣的可以自己去看源码吧。

方法的主体从行715开始直到结束,定义了Sizzle构造函数,若干工具方法和Sizeele静态方法及属性,概览看下图,由于内容太多,只截部分:
图1

1、Sizzle构造函数:

function Sizzle( selector, context, results, seed ){
    var m, i, elem, nid, match, groups, newSelector,
		newContext = context && context.ownerDocument,
        //上下文默认为document,节点类型默认为9
		nodeType = context ? context.nodeType : 9;
	results = results || [];

	// 对选择器值为非字符串、为假、节点类型不符合要求时的返回值进行处理
	if ( typeof selector !== "string" || !selector ||
		nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) {

		return results;
	}

	// 操作HTML文档
	if ( !seed ) {

		if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) {
			setDocument( context );
		}
		context = context || document;

		if ( documentIsHTML ) {

			if ( nodeType !== 11 && (match = rquickExpr.exec( selector )) ) {

				// ID 选择器
				if ( (m = match[1]) ) {

					// 文档内容
					if ( nodeType === 9 ) {
						if ( (elem = context.getElementById( m )) ) {

							if ( elem.id === m ) {
								results.push( elem );
								return results;
							}
						} else {
							return results;
						}

					// 元素内容 
					} else {

						if ( newContext && (elem = newContext.getElementById( m )) &&
							contains( context, elem ) &&
							elem.id === m ) {

							results.push( elem );
							return results;
						}
					}

				// 类型选择器
				} else if ( match[2] ) {
					push.apply( results, context.getElementsByTagName( selector ) );
					return results;

				// Class 选择器
				} else if ( (m = match[3]) && support.getElementsByClassName &&
					context.getElementsByClassName ) {

					push.apply( results, context.getElementsByClassName( m ) );
					return results;
				}
			}

			if ( support.qsa &&
				!compilerCache[ selector + " " ] &&
				(!rbuggyQSA || !rbuggyQSA.test( selector )) ) {

				if ( nodeType !== 1 ) {
					newContext = context;
					newSelector = selector;

				} else if ( context.nodeName.toLowerCase() !== "object" ) {

					if ( (nid = context.getAttribute( "id" )) ) {
						nid = nid.replace( rcssescape, fcssescape );
					} else {
						context.setAttribute( "id", (nid = expando) );
					}

					groups = tokenize( selector );
					i = groups.length;
					while ( i-- ) {
						groups[i] = "#" + nid + " " + toSelector( groups[i] );
					}
					newSelector = groups.join( "," );

					newContext = rsibling.test( selector ) && testContext( context.parentNode ) ||
						context;
				}

				if ( newSelector ) {
					try {
						push.apply( results,
							newContext.querySelectorAll( newSelector )
						);
						return results;
					} catch ( qsaError ) {
					} finally {
						if ( nid === expando ) {
							context.removeAttribute( "id" );
						}
					}
				}
			}
		}
	}

    // 返回 调用select()方法后的值
	return select( selector.replace( rtrim, "$1" ), context, results, seed );
}

Sizzle函数是整个css选择器的入口函数。

喜欢本文请扫下方二维码,关注微信公众号: 前端小二,查看更多我写的文章哦,多谢支持。
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_34832846/article/details/86298051