版权声明:本文为微信公众号前端小二版权所有,如需转载可私信或关注微信公众号留言。 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选择器的入口函数。
喜欢本文请扫下方二维码,关注微信公众号: 前端小二,查看更多我写的文章哦,多谢支持。