码迷,mamicode.com
首页 > 其他好文 > 详细

Sizzle.filter [ 源代码分析 ]

时间:2015-09-19 15:05:18      阅读:186      评论:0      收藏:0      [点我收藏+]

标签:

最近的研究已Sizzle选择,对于原理中我们也不得不佩服!

Sizzle中间filter办法。主要负责元素表达式过滤块的集合,在内部的方法调用Sizzle.selector.fitler滤波操作的操作方法。

Sizzle.filter要点5:

1 使用LeftMatch确定表达式类型。

2 调用Sizzle.selectors.preFilter预过虑函数,运行过滤前的修正。

3 调用Sizzle.selectors.filter[ type ] 中相应的过滤函数,运行过滤操作,假设返回false,刚将元素集合中的相应位置的元素替换为false;

4 删除表达式中已过滤的部分

5 反复1 - 4 步骤


源代码例如以下:

Sizzle.filter = function( expr, set, inplace, not ) {
	//expr 块表达式
	//set 待过滤的元素集合
	//inplace 是否替换,假设为true,那么当set中的元素与expr不匹配时,刚将不匹配的元素替换为false,
	//否则。构造新的数组,仅仅保留匹配的元素
	//not: 假设为true,则去掉匹配元素,保留不匹配元素。假设为false,则保留匹配元素,去掉不匹配元素
	var match, anyFound,
		type, found, item, filter, left,
		i, pass,
		old = expr,
		result = [],
		curLoop = set,
		isXMLFilter = set && set[0] && Sizzle.isXML( set[0] );
	//while 循环,无限循环用expr过滤set元素,直到expr为空,由于在最后会将已经匹配过的部分删除,所以expr会越来越短
	while ( expr && set.length ) {
		for ( type in Expr.filter ) {
			//这里用来确定表达式类型。依据leftMatch正则
			//这里是match正则,LeftMatch仅仅是要该正则加上了前缀和后缀
			/*
			match: {
				ID: /#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,
				CLASS: /\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,
				NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/,
				ATTR: /\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?

=)\s*(?:(['"])(.*?

)\3|(#?(?

:[\w\u00c0-\uFFFF\-]|\\.)*)|)|)\s*\]/, TAG: /^((?

:[\w\u00c0-\uFFFF\*\-]|\\.)+)/, CHILD: /:(only|nth|last|first)-child(?:\(\s*(even|odd|(?

:[+\-]?\d+|(?

:[+\-]?\d*)?

n\s*(?:[+\-]\s*\d+)?))\s*\))?/, POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/, PSEUDO: /:((?

:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/ }, */ if ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) { filter = Expr.filter[ type ]; //确定前缀 left = match[1]; anyFound = false; match.splice(1,1); //这里官方说是匹配 \\ 假设是 \\ 那么表示后面的元素都是被转义,刚不须要再去过滤, //只是个人觉得这个地方似乎无效的 left.subster(left.length - 1) //这个字符的长度仅仅会是1 怎么会和 \\ 相等呢 if ( left.substr( left.length - 1 ) === "\\" ) { continue; } //重置result为空数组,用于缩小候选集,result用来存放通过过滤的元素 if ( curLoop === result ) { result = []; } if ( Expr.preFilter[ type ] ) { //这里会进行预过滤操作,主要对表达式进行改动正,如转义\\,取出空格等 //针对不同和类型,会有不同的方式,详情能够见preFilter方法 match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter ); /*match: 1 true: 继续须要运行过滤。尚不到运行过虑函数的时候,直接运行continue,不再去调用filter方法。如pos,child 2 false: 已经运行了过滤,缩小了候选集如:CLASS 3 字符串: 修正之后的过滤參数。后面会继续调用相应的过虑函数 */ if ( !match ) { anyFound = found = true; } else if ( match === true ) { continue; } } //返回的是修正的过滤參数,刚继续运行 if ( match ) { //遍历候选集中的元素 for ( i = 0; (item = curLoop[i]) != null; i++ ) { //元素存在 if ( item ) { //对其进行过滤,返回结果 found = filter( item, match, i, curLoop ); //这里与 not 进行 异或 操作 pass = not ^ found; //为替换模式,而且found 不为空 if ( inplace && found != null ) { //假设通过。那么为true if ( pass ) { anyFound = true; } else { //否则将元素替换为false curLoop[i] = false; } } else if ( pass ) { //这要须要注意的是既然pass为真了。 那么就不须要推断了found,由于pass为found与not异或的结果 //假设通过了,而且为非替换模式,那么将元素放入到新的数组result中 result.push( item ); anyFound = true; } } } } //found不为undefined if ( found !== undefined ) { if ( !inplace ) { //非替换模式,将结果复制给curLoop, curLoop = result; } //删除已经过滤过了的部分表达式 expr = expr.replace( Expr.match[ type ], "" ); //不匹配,返回空 if ( !anyFound ) { return []; } //这里的break,说明已经进行过一次过虑,已经找到相应的type,能够选择跳出当前type的循环, break; } } } // 这里主要是匹配,假设最后过滤的表达式没有变化。那么觉得过滤表达式有问题 if ( expr === old ) { if ( anyFound == null ) { Sizzle.error( expr ); } else { break; } } //备份expr,继续循环 old = expr; } //返回过滤的结水果 return curLoop; };



版权声明:本文博主原创文章。转载声明转载地址。

Sizzle.filter [ 源代码分析 ]

标签:

原文地址:http://www.cnblogs.com/lcchuguo/p/4821377.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!