jQuery源码分析-04选择器-Sizzle-工作原理分析
作者:手浪用户2502876054 | 来源:互联网 | 2022-10-13 17:23
在分析Sizzle源码之前,先整理一下选择器的工作原理,先明确一些选择器中用到的名词,后边阅读时不会有歧义
作者:nuysoft/高云 QQ:47214707 EMail:nuysoft@gmail.com 声明:本文为原创文章,如需转载,请注明来源并保留原文链接。 在分析Sizzle源码之前,先整理一下选择器的工作原理 先明确一些选择器中用到的名词,后边阅读时不会有歧义: 选择器表达式: "div > p" 块表达式: "div" "p" 并列选择器表达式: "div, p" 块分割器: Sizzle中的chunker正则,对选择器表达式从左向右分割出一个个块表达式 查找器: 对块表达式进行查找,找到的DOM元素数组叫候选集 过滤器: 对块表达式和候选集进行过滤 关系过滤器 对块表达式之间的关系进行过滤,共有四种关系:"+" 紧挨着的兄弟关系;">" 父子关系;"" 祖先关系;"~" 之后的所有兄弟关系 候选集: 查找器的结果,待过滤器进行过滤 映射集: 候选集的副本,过滤器和关系过滤器对映射集进行过滤 工作流程: 1. 使用块分割器对选择器表达式进行分割,从左向右 如果遇到用逗号","分割的并列选择器表达式,只分割至第一个逗号前边的选择器表达式1,将剩余部分记录下来 2. 对最后一个块表达式进行查找Sizzle.find,结果放入候选集set,并将块表达式中匹配的字符串部分删除 查找器Sizzle.find从正则集Expr.match获取对应的正则表达式,对块表达式进行匹配,匹配成功则从查找函数集Expr.find获取对应的查找函数执行 查找顺序定义在Expr.order中,依次是:ID CLASS NAME TAG,查找时CLASS需要浏览器支持getElementsByClassName Expr.match中设定了ID CLASS NAME ATTR TAG CHILD POS PSEUDO的正则匹配表达式 3. 如果最后一个块表达式不为空(字符串),过滤器Sizzle.filter对set进行过滤 过滤器Sizzle.filter仅对单个块表达式起作用,仅对候选集set中的元素起作用,检查候选集set中的元素满足剩余的块表达式 在过滤器Sizzle.filter的过滤过程中,不符合条件的被设置为false,符合条件的不做修改 过滤时从正则集Expr.leftMatch获取对应的正则表达式,对块表达式进行匹配,匹配成功则从Expr.filter获取对应的过滤函数执行 Expr.leftMatch定义了与Expr.match同样数量的正则表达式:ID CLASS NAME ATTR TAG CHILD POS PSEUDO 过滤函数集Expr.filter定义了PSEUDO CHILD ID TAG CLASS ATTR POS的过滤函数 过滤器Sizzle.filter进行过滤之前,会先调用预过滤器Expr.preFilter对过滤所需的参数进行修正,但是CLASS是个例外 在CLASS进行预过滤时做了优化,直接将匹配class的元素作为候选集返回,缩小过滤范围,缩小候选集范围 将以上查找和过滤得到候选集set复制,放入映射集checkSet,后边的过滤操作在checkSet上进行 对最后一个块表达式的查找和过滤到这里结束,得到一个候选集set和映射集checkSet 4. 在映射集checkSet上将剩余的块表达式从右向左进行过滤,根据与前一个块表达式的关系,从关系过滤器集Expr.relative中获取对应的函数执行关系过滤 在关系过滤器Expr.relative的过滤过程中,不符合条件的被设置为false,符合条件的则被设置为父元素、祖先元素、兄长元素 元素之间的关系共有四种:"+" 紧挨着的兄弟关系;">" 父子关系;"" 祖先关系;"~" 之后的所有兄弟关系 在关系过滤器Expr.relative的过滤过程中,如果遇到块表达式是标签TAG的情况,则直接比较标签类型nodeName是否相等 如果不是标签TAG的情况,则会调用过滤器Sizzle.filter进行过滤,过滤过程见第3步 从右向左过滤,直到所有块表达式全部过滤完 5. 根据过滤后的映射集checkSet,从候选集set中挑选最终的结果集,在映射集checkSet中 如果是null、false,将被过滤 如果不是Element(nodeType===1),将被过滤 如果上下文不是Document而是某个Element,不是Element的子元素的,将被过滤 6. 如果存在并列表达式,重复1~5,并将得到的最终结果集合并、排序、去重 如果仅有一个选择器表达式,没有并列选择器表达式,不需要排序 以下过程不属于Sizzle,属于jQuery对Sizzle的扩展 7. 如果存在多个上下文,对每个上下文重复1~6 多个上下文例子:$('div').find('div > p'),$('div')可能找到多个div 其实第7步是jQuery选择器的入口,从第7步去调用1~6,调用时传入一个空的jQuery对象作为结果集 默认以document为上下文:(context || rootjQuery).find( selector ) 8. 将从多个上下文找到的结果集合并、去重,返回结果集 done!
推荐阅读
本文提供了一个详尽的前端开发资源列表,涵盖了从基础入门到高级应用的各个方面,包括HTML5、CSS3、JavaScript框架及库、移动开发、API接口、工具与插件等。 ...
[详细]
蜡笔小新 2024-11-23 12:05:53
本文介绍了如何使用jQuery获取浏览器窗口的可视区域高度、文档的整体高度以及宽度等关键尺寸信息,包括边界、填充和边距在内的完整尺寸。 ...
[详细]
蜡笔小新 2024-11-24 12:57:23
本文探讨了互联网服务提供商(ISP)如何可能篡改或插入用户请求的数据流,并提供了有效的技术手段来防止此类劫持行为,确保网络环境的安全与纯净。 ...
[详细]
蜡笔小新 2024-11-23 09:41:45
本文介绍了如何在 MongoDB 中使用正则表达式进行数据排除查询,特别关注了通过 $regex 和 $nin 操作符来过滤特定模式的数据。 ...
[详细]
蜡笔小新 2024-11-22 21:20:42
本文综述了视觉Transformer在计算机视觉领域的应用,从原始Transformer出发,详细介绍了其在图像分类、目标检测和图像分割等任务中的最新进展。文章不仅涵盖了基础的Transformer架构,还深入探讨了各类增强版Transformer模型的设计思路和技术细节。 ...
[详细]
蜡笔小新 2024-11-22 19:53:16
本文详细介绍了 JavaScript 中 Split 方法的使用方式和一些实用技巧。通过示例,我们将探讨如何利用 Split 方法有效地分割字符串,并获取所需的数据。 ...
[详细]
蜡笔小新 2024-11-22 10:30:21
本文深入探讨了逻辑回归在机器学习中的应用,并详细解释了如何通过正则化等方法来有效避免模型的过拟合问题。 ...
[详细]
蜡笔小新 2024-11-21 15:22:20
本文探讨了在使用PHP进行后端开发时,遇到的一个常见问题:即在本地环境中能够正常通过CURL获取远程网页内容,但在服务器上却无法实现。我们将分析可能的原因并提供解决方案。 ...
[详细]
蜡笔小新 2024-11-21 10:31:32
Web动态服务器Python基本实现 ...
[详细]
蜡笔小新 2024-11-21 08:01:30
Python正则表达式快速参考常用函数:re.match():从字符串的起始位置匹配一个正则表达式。re.search():扫描整个字符串并返回第一个成功的匹配。re.s ...
[详细]
蜡笔小新 2024-11-19 18:22:57
本文详细介绍了Java中常用的字符串截取方法及其应用场景,帮助开发者更好地理解和使用这些方法。 ...
[详细]
蜡笔小新 2024-11-17 18:10:47
本文详细探讨了Spring框架中遇到的NoSuchBeanDefinitionException异常,具体涉及com.thinkplatform.dao.UserLogDao Bean未定义的问题,并提供了相应的解决方案。 ...
[详细]
蜡笔小新 2024-11-17 17:16:33
本文介绍了 PHP 的基本概念、服务器与客户端的工作原理,以及 PHP 如何与数据库交互。同时,还涵盖了常见的数据库操作和安全性问题。 ...
[详细]
蜡笔小新 2024-11-17 15:45:08
蜡笔小新 2024-11-17 13:29:11
本打算教一步步实现koa-router,因为要解释的太多了,所以先简化成mini版本,从实现部分功能到阅读源码,希望能让你好理解一些。希望你之前有读过koa源码,没有的话,给你链接 ...
[详细]
蜡笔小新 2024-11-17 13:09:46
手浪用户2502876054
这个家伙很懒,什么也没留下!