您的位置:首页 > Web前端 > JQuery

JQuery日记_5.14 Sizzle选择器(七)

2014-05-16 18:49 417 查看
上篇说道,tokenize方法会把selector分割成一个个selector逻辑单元(如div>a是三个逻辑单元 'div','>','a')并为之片段赋予对应类型的过滤函数。

for ( type in Expr.filter ) {
if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] ||
(match = preFilters[ type ]( match ))) ) {
matched = match.shift();
tokens.push({
value: matched,
type: type,
matches: match
});
soFar = soFar.slice( matched.length );
}
}

然后选出最后selector逻辑单元(是指由需要上下文的选择器,如id,tag,class等)所对应的元素集作为从右向左(一般情况)过滤的候选元素集,match(正则捕获组)是selector逻辑片段的解析结果(如[arr="111"]根据正则解析为arr,",=,111 ),在selector逻辑片段是ATTR、CHILD、PSEUDO是需要调用preFilter对match进行修正.
preFilter: {
//match是捕获组
//假设:[arr^='val']
"ATTR": function( match ) {
//attr的第一个捕获 组是arr,将其中的转码变成原来的字符
match[1] = match[1].replace( runescape, funescape );

// Move the given value to match[3] whether quoted or unquoted
// 将val放到捕获组3里,原来的捕获组3捕获'或"
match[3] = ( match[4] || match[5] || "" ).replace( runescape, funescape );
//如果捕获组2是~=,在match[3]前后加空格,以方便匹配单个单词
if ( match[2] === "~=" ) {
match[3] = " " + match[3] + " ";
}
//match[0] = '[arr^='val']'
//match[1] = 'arr'
//match[2] = '='
//match[3] = '111'
return match.slice( 0, 4 );
},

"CHILD": function( match ) {
/*  例如nth-child(-2n+1)的捕获组
mathc[1] nth
mathc[2] child
mathc[3] 2n+1
mathc[4] 2n
mathc[5] -
mathc[6] 2
mathc[7] +
mathc[8] 1
*/
match[1] = match[1].toLowerCase();
// nth必须需要参数
if ( match[1].slice( 0, 3 ) === "nth" ) {
// nth-* requires argument
if ( !match[3] ) {
Sizzle.error( match[0] );
}

// numeric x and y parameters for Expr.filter.CHILD
// remember that false/true cast respectively to 0/1
// xn + y
// 将even,odd修正为xn+y,match[4]修正为+-x
match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) );
// 将match[5]替换为+-y
match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" );

// other types prohibit arguments
// 除nth外其他类型禁止参数
} else if ( match[3] ) {
Sizzle.error( match[0] );
}
// match[0] :nth-child(-2n+1)
// match[1] nth
// match[2] child
// match[3] -2n+1
// match[4] -2
// match[5] 1
// match[6] 2
// match[7] +
// match[8] 1
return match;
},
/**
* match[1] :后伪类类型
* match[2] 伪类参数
* match[3] 参数中的'或者"
* match[4] 除去'或"的伪类
*/
"PSEUDO": function( match ) {
var excess,
unquoted = !match[5] && match[2];

//是CHILD伪类,返回null
if ( matchExpr[ "CHILD"].test( match[0] ) ) {
return null;
}

// Accept quoted arguments as-is
// 参数有引号
//将match[2]替换为无引号的match[4]参数
if ( match[3] && match[4] !== undefined ) {
match[2] = match[4];

// Strip excess characters from unquoted arguments
// 除去带引号的参数的多余字符
} else if ( unquoted && rpseudo.test( unquoted ) &&
// Get excess from tokenize (recursively)
//excess多余字符的长度
(excess = tokenize( unquoted, true )) &&
//excess多余参数的索引位置,excess是个负值,以便截取到多余字符之前
(excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) {

// excess is a negative index
match[0] = match[0].slice( 0, excess );
match[2] = unquoted.slice( 0, excess );
}

// Return only captures needed by the pseudo filter method (type and argument)
return match.slice( 0, 3 );
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: