1 jQuery 对象Sizzle.selectors.relative中存放了块间关系符和相应的块间关系过滤函数,称为“块间关系过滤函数集”

块间关系符共同拥有4种,其含义和过滤方式如图所看到的。

在函数Sizzle( selector, context, results, seed )从右向左进行过滤时,块间关系过滤函数被

调用,用于检查映射集checkSet中的元素是否匹配块间关系符左側的块表达式。调用时的參

数格式为:

Sizzle.selectors.relative[ 块间关系符 cur  ](  映射集 checkSet,  左側块表达式pop,
contextXML );

块间关系过滤函数接受3个參数:

‰ ‰參数checkSet:映射集,对该元素集合运行过滤操作。

‰ ‰參数part:大多数情况下是块间关系符左側的块表达式,该參数也能够是DOM元素。

‰ ‰參数isXML:布尔值,指示是否执行在一个XML文档中。

块间关系过滤函数实现的3个关键过程例如以下:

1)遍历映射集checkSet。

2)依照块间关系符查找每一个元素的兄弟元素、父元素或祖先元素。

3)检查找到的元素是否匹配參数part,并替换映射集checkSet中相应位置的元素。

a. 假设參数part是标签,则检查找到的元素其节点名称nodeName是否与之相等,

假设相等则替换为找到的元素,不相等则替换为false。

b. 假设參数part是DOM元素,则检查找到的元素是否与之相等,假设相等则替换

为true,不相等则替换为false。

c. 假设參数part是非标签字符串,则调用方法Sizzle.filter( selector, set, inplace, not )过滤。

也就是说,遍历结束后,映射集checkSet中的元素可能会是兄弟元素、父元素、

祖先元素、true或false。



1 块间关系符"+"匹配选择器"prev + next",即匹配全部紧接在元素prev后的兄弟元素

next。比如,$("div + span")、$(".lastdiv + span")。对于从右向左的查找方式,则是检查元

素next之前的兄弟元素是否匹配块表达式prev。

var Expr = Sizzle.selectors = {
relative: {
"+": function(checkSet, part){
//检查參数是否为字符串
var isPartStr = typeof part === "string",
//指示參数part是否为标签字符串
isTag = isPartStr && !rNonWord.test( part ),
//isPartStrNotTag:指示參数part是否是非标签字符串。
isPartStrNotTag = isPartStr && !isTag; if ( isTag ) {
part = part.toLowerCase();
}
/*
遍历映射集checkSet,查找每一个元素的前一个兄弟元素,并替换映
射集checkSet中相应位置的元素,有下面3个逻辑分支:
‰1 假设未找到兄弟元素,则替换为false。
2 ‰假设找到了兄弟元素,而且參数part是标签,则检查兄弟元素的节点名称nodeName
是否与之相等,假设相等则替换为兄弟元素,不相等则替换为false。
3 ‰假设找到了兄弟元素,而且參数part是DOM元素,则检查二者是否相等,假设相等
则替换为true,不相等则替换为false。
因此,在遍历结束后,映射集checkSet中的元素可能会是兄弟元素、true或false。
*/
for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) {
if ( (elem = checkSet[i]) ) {
/*在遍历兄弟元素的同一时候过滤掉非元素节点,而且仅仅要取到一个兄弟元素就
退出while循环。*/
while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) { } checkSet[i] = isPartStrNotTag || elem && elem.node
Name.toLowerCase() === part ?
elem || false :
elem === part;
}
}
/*
假设參数part是非标签字符串,则调用方法Sizzle.filter( selector,
set, inplace, not )过滤映射集checkSet。对于參数part是标签和DOM元素的情况,在前面遍
历映射集checkSet时已经处理过了。
*/
if ( isPartStrNotTag ) {
Sizzle.filter( part, checkSet, true );
}
},
},
};

2 块间关系符">"用于选择器"parent > child",即匹配父元素parent下的子元素child。

比如,$("div + span")、$(".lastdiv + span")。对于从右向左的查找方式,则是检查子元素

child的父元素是否匹配块表达式parent。

var Expr = Sizzle.selectors = {
relative: {
">": function( checkSet, part ) {
var elem,
isPartStr = typeof part === "string",
i = 0,
l = checkSet.length;
/*
假设參数part是标签,则遍历映射集checkSet,查找每一个元素的
父元素,并检查父元素的节点名称nodeName是否与參数part相等,假设相等则替换映射集
checkSet中相应位置的元素为父元素,不相等则替换为false。
*/
if ( isPartStr && !rNonWord.test( part ) ) {
part = part.toLowerCase(); for ( ; i < l; i++ ) {
elem = checkSet[i]; if ( elem ) {
var parent = elem.parentNode;
checkSet[i] = parent.nodeName.toLowerCase() === part ?
parent : false;
}
}
} else {
/*
假设參数part不是标签,则可能是非标签字符串或DOM元素,同
样遍历映射集checkSet,查找每一个元素的父元素,并替换映射集checkSet中相应位置的元
素,在这个过程中有下面2个逻辑分支:
‰1 ‰假设參数part是非标签字符串,则在遍历映射集checkSet的过程中,替换映射集
checkSet中相应位置的元素为父元素,遍历结束后调用方法Sizzle.filter( selector, set,
inplace, not )过滤映射集checkSet。
‰2 ‰假设參数part是元素,则在遍历映射集checkSet时,检查每一个元素的父元素是否与
之相等,假设相等则替换映射集checkSet中相应位置的元素为true,不相等则替换为
false。
因此,在遍历结束后,映射集checkSet中的元素可能会是父亲元素、true或false。
*/
for ( ; i < l; i++ ) {
elem = checkSet[i]; if ( elem ) {
checkSet[i] = isPartStr ?
elem.parentNode :
elem.parentNode === part;
}
} if ( isPartStr ) {
Sizzle.filter( part, checkSet, true );
}
}
},
},
};

3 块间关系符""用于选择器"ancestor descendant",即匹配祖先元素ancestor的全部后代

元素descendant。比如,$("div button")、$("div .btn")。对于从右向左的查找方式,则是检

查后代元素descendant的祖先元素是否匹配块表达式ancestor。

var Expr = Sizzle.selectors = {
relative: {
"": function(checkSet, part, isXML){
var nodeCheck,
doneName = done++,
checkFn = dirCheck;
/*
‰1 假设參数part是非标签字符串或DOM元素,则调用函数dirCheck()过滤映射集
checkSet。
‰2 假设參数part是标签,则调用函数dirNodeCheck()过滤映射集checkSet。
调用函数dirCheck()和dirNodeCheck()时的參数格式为:
checkFn( 方向 "parentNode/previousSibling", 块表达式 part, 缓存计数器 doneName, 映
射集 checkSet, nodeCheck, isXML )
函数dirCheck()和dirNodeCheck()会遍历映射集checkSet,查找每一个元素的祖先元素,
并检查是否有祖先元素匹配參数part,同一时候替换映射集checkSet中相应位置的元素。
*/
if ( typeof part === "string" && !rNonWord.test( part ) ) {
part = part.toLowerCase();
nodeCheck = part;
checkFn = dirNodeCheck;
} checkFn( "parentNode", part, doneName, checkSet, nodeCheck, isXML );
},
},
};

4 块间关系符"~"用于选择器"prev~siblings",即匹配元素prev之后的全部兄弟元

素siblings。比如,$('div~p')。对于从右向左的查找方式,则是检查元素siblings之前的

兄弟元素是否匹配块表达式prev。

Sizzle.selectors.relative["~"]( checkSet, part )的源代码实现与Sizzle.selectors.relative[""]

( checkSet, part )差点儿一样,两者的差别只在于调用函数dirCheck()和dirNodeCheck()时第

一个參数的值不同,前者是"previousSibling",后者则是"parentNode"。

相关代码例如以下所看到的:

var Expr = Sizzle.selectors = {
relative: {
"~": function( checkSet, part, isXML ) {
var nodeCheck,
doneName = done++,
checkFn = dirCheck; if ( typeof part === "string" && !rNonWord.test( part ) ) {
part = part.toLowerCase();
nodeCheck = part;
checkFn = dirNodeCheck;
} checkFn( "previousSibling", part, doneName, checkSet, nodeCheck,
isXML );
}
},
};

Sizzle.selectors.relative [ 源代码分析 ]的更多相关文章

  1. [转]JQuery - Sizzle选择器引擎原理分析

    原文: https://segmentfault.com/a/1190000003933990 ---------------------------------------------------- ...

  2. Sizzle.filter [ 源代码分析 ]

    最近的研究已Sizzle选择,对于原理中我们也不得不佩服! Sizzle中间filter办法.主要负责元素表达式过滤块的集合,在内部的方法调用Sizzle.selector.fitler滤波操作的操作 ...

  3. 转:RTMPDump源代码分析

    0: 主要函数调用分析 rtmpdump 是一个用来处理 RTMP 流媒体的开源工具包,支持 rtmp://, rtmpt://, rtmpe://, rtmpte://, and rtmps://. ...

  4. Android 中View的绘制机制源代码分析 三

    到眼下为止,measure过程已经解说完了,今天開始我们就来学习layout过程.只是在学习layout过程之前.大家有没有发现我换了编辑器,哈哈.最终下定决心从Html编辑器切换为markdown编 ...

  5. spark(1.1) mllib 源代码分析

    在spark mllib 1.1加入版本stat包,其中包括一些统计数据有关的功能.本文分析中卡方检验和实施的主要原则: 一个.根本 在stat包实现Pierxunka方检验,它包括以下类别 (1)适 ...

  6. LIRe 源代码分析 3:基本接口(ImageSearcher)

    ===================================================== LIRe源代码分析系列文章列表: LIRe 源代码分析 1:整体结构 LIRe 源代码分析 ...

  7. RTMPdump(libRTMP) 源代码分析 9: 接收消息(Message)(接收视音频数据)

    ===================================================== RTMPdump(libRTMP) 源代码分析系列文章: RTMPdump 源代码分析 1: ...

  8. RTMPdump(libRTMP) 源代码分析 6: 建立一个流媒体连接 (NetStream部分 1)

    ===================================================== RTMPdump(libRTMP) 源代码分析系列文章: RTMPdump 源代码分析 1: ...

  9. Cocos2d-x 源代码分析 : Scheduler(定时器) 源代码分析

    源代码版本号 3.1r,转载请注明 我也最终不out了,開始看3.x的源代码了.此时此刻的心情仅仅能是wtf! !!!!!!! !.只是也最终告别CC时代了. cocos2d-x 源代码分析文件夹 h ...

随机推荐

  1. jquery动态加入删除一行数据

    <html> <head> <title>加入.删除一行</title> <meta http-equiv="content-type& ...

  2. error C2504: “CActiveXDocControl”: 基类没有定义

    这样的错误,通常,第一个文件失败: 1.相互头包括 2.头文件秩序 此错误是编译错误,和"inclued头文件"有关 问题描写叙述 有三个头文件AgentSDK.h.AA.h.BB ...

  3. Google 开源项目的风格指南

    谷歌C++代码风格指南.农业所需的代码.更难得的是不FQ,决定性的最爱!! . http://zh-google-styleguide.readthedocs.org/en/latest/google ...

  4. HTTP求

    client联系server后,至server获取问题 Web 新闻资源,简称client至server发送一个 HTTP 求. 一个完整的 HTTP 该请求包含以下示例: ① ②若干消息头(请求头) ...

  5. android下获取无线wif信号、ssid、MAC等操作类

    一个android下获取无线wif信号.ssid.MAC等操作的类. WifiAdmin.java package com.afu; import java.util.List; import and ...

  6. emeditor 配置教程

    1.众多的图形界面配置功能 通过查看EmEditor的安装目录,可以发现,EmEditor有几个配置文件,理论上应该可以通过修改配置文件来达到配置EmEditor的目 的.然而,打开配置文件一看,如果 ...

  7. BZOJ 1052 HAOI2007 覆盖问题 二分法答案+DFS

    标题效果:特定n点.涵盖所有的点与同方三面.斧头要求方垂直边界,最小平方的需求方长值 最大值至少.答案是很明显的二分法 但验证是一个问题 考虑仅仅有三个正方形,故用一个最小矩形覆盖这三个正方形时至少有 ...

  8. TCP/IP具体解释--nagle算法和TCP_NODELAY

    在client一直给server发送小数据的时候,接受到一个回应会在非常长的时间以后,可是将多个小数据写操作合并成一个写操作,问题就没了. 这个事件的缘由可能是TCP_NODELAY的原因 如今大概明 ...

  9. 可以部署在广域网执行QQ高仿版 GG2014 (源代码)

      距上次GG V3.7版本号(可在广域网部署执行的QQ高仿版 -- GG叽叽V3.7.优化视频聊天.控制很多其它相关细节)的公布.已经有50天了,这50天对于GG来说.是一个重大的飞跃. 由于这段时 ...

  10. 大哥可以写KMP该——达到strstr()

    在最后采访,面试官要求实现strstr(),当场就蒙了. 这个题目是模式匹配问题.<算法导论>里列出了几种字符串匹配算法: 朴素算法 |  Rabin-Karp | 有限自己主动机算法 | ...