3.2 Sizzle引擎概述
Sizzle是jQuery的CSS选择器模块,同时也是纯JavaScript CSS选择器引擎,能够方便用户轻松地引入各种库中。Sizzle API由以下3部分组成。
公共API:用户与之交互部分。
扩展API:用于修改选择器引擎。
内部API:在Sizzle内部使用。
3.2.1 Sizzle特征
Sizzle具有如下特征:
完全独立,不依赖任何库。
高效运行,最常用的选择器具有很强的竞争性能。
非常小,被压缩后只有4KB。
易于使用,API具有高度可扩展性。
通过事件委托可以实现最佳性能。
代码开源,由jQuery基金会持有所有代码,开放共享。
3.2.2 Sizzle选择器功能
Sizzle选择器主要功能如下:
支持CSS 3选择器。
支持完整的Unicode。
支持转义选择器,如#id\:value。
支持包含文本,如:contains(text)。
支持复合选择器,如:not :not(a#id)。
支持多重选择,如:not :not(div,p)。
支持不包含属性值,如[name!=value]。
支持判断选择器,如:has(div)。
支持位置选择器,如:first、:last、:even、:odd、:gt、:lt、:eq。
支持易用表单选择器,如:input、:text、:checkbox、:file、:password、:submit、:image、:reset、:button。
支持标题选择器,如:header。
3.2.3 Sizzle代码功能
Sizzle代码具有如下功能:
为语法问题提供有意义的错误消息。
使用单个代码路径,不用XPath。
不再使用浏览器探测。
Caja兼容代码。
3.2.4 Sizzle参考
Sizzle官网:https://sizzlejs.com/。
Sizzle文档:https://github.com/jquery/sizzle/wiki。
GitHub项目(源代码):https://github.com/jquery/sizzle/tree/master。
Sizzle讨论组:http://groups.google.com/group/sizzlejs。
3.2.5 浏览器支持
桌面
Chrome 16+
Edge 12+
Firefox 3.6+
Internet Explorer 7+
Opera 11.6+
Safari 4.0+
注意:独立Sizzle和包含Sizzle的库之间,浏览器支持可能会有所不同。
Internet Explorer 6的解决方案仍在代码中,但浏览器不再被主动测试。
移动
Android 2.3+
iOS 5.1+
3.2.6 Sizzle选择器
Sizzle支持几乎所有的CSS 3选择器,包括转义的选择器(如foo\+bar)、Unicode选择器和以文档顺序返回的结果。但是,不支持以下CSS伪选择器:
:hover
:active
:visited
:link
因为需要额外的DOM事件监听器来跟踪元素的状态。
而下面这些CSS 3伪选择器在Sizzle 1.9版本之前不被支持:
:target
:root
:nth-last-child
:nth-of-type、:nth-last-of-type、:first-of-type、:last-of-type、:only-of-type
:lang()
除了CSS 3选择器外,Sizzle又增加了其他选择器,具体说明如下:
not()完全选择列表::not(a.b)、:not(div > p)、:not(div, p)。
嵌套伪选择器::not(:has(div:first-child))。
[NAME!=VALUE]:匹配NAME属性与指定值不匹配的元素,相当于:not([NAME=VALUE])。
:contains(TEXT):含有textContent的元素,包含单词'TEXT',区分大小写。
:header:标题元素,包括h1、h2、h3、h4、h5和h6元素。
:parent:包含至少有一个子节点(文本或元素)的元素。
:selected:当前选择的元素。
添加的表单选择器说明如下:
:input:输入元素。
:button:输入元素是按钮,或type="button"的按钮。
:checkbox、:file、:image、:password、:radio、:reset、:submit、:text:具有指定类型的输入元素。
注意:input、button、select和textarea都被认为是输入元素。
添加的位置选择器说明如下:
:first、:last:第一个或最后一个匹配元素。
:even、:odd:偶数或奇数元素。
:eq、:nth:第n个元素,如:eq(5)匹配第6个元素。
:lt、:gt:位于指定位置上方或下方的元素。
注意:位置索引从0开始。在这种情况下,位置是指在选择之后,基于文档顺序的元素在集合中的位置。例如,div:first,首先返回在页面中包含第一个div的数组,而div:first em将定位到页面上的第一个div,然后选择所有em元素。
3.2.7 公共API
下面是Sizzle选择器引擎主要公共函数。
1.Sizzle()
Sizzle()是Sizzle查找元素的主要函数。语法格式如下:
Sizzle( String selector[, DOMNode context[, Array results]] )
参数说明如下:
selector:一个CSS选择器,字符串类型。
context:指定查找范围的上下文元素,如文档或文档片段。默认为文档。注意,在2.1版本之前,不支持文档片段。
results:附加查找结果的数组,或类似数组的对象(如jQuery)。
该函数先判断浏览器是否支持querySelectorAll。如果支持querySelectorAll,则优先使用querySelectorAll;否则使用传统方法进行匹配。最后返回一个数组,包含与选择器匹配的所有元素。
2.Sizzle.matchesSelector()
Sizzle.matchesSelector()判断给定元素是否与选择器匹配。语法格式如下:
Sizzle.matchesSelector( DOMElement element, String selector )
参数说明如下:
element:一个DOM元素,Sizzle将测试选择器的DOMElement。
selector:一个CSS选择器,字符串类型。
该函数使用本地函数matchesSelector(如果可用)进行检测,最后返回一个布尔值,如果匹配则返回true,否则返回false。
3.Sizzle.matches()
Sizzle.matches()根据给定的选择器,返回匹配元素。语法格式如下:
Sizzle.matches( String selector, Array<DOMElement> elements )
参数说明如下:
selector:一个CSS选择器,字符串类型。
elements:使用指定选择器进行过滤的DOMElement数组。
最后返回一个数组,数组中包含与给定选择器匹配的元素。
3.2.8 扩展API
在Sizzle中,Sizzle.selectors.match.NAME = RegExp包含了用于将选择器解析为不同部分的正则表达式,用于查找和过滤。每个正则表达式的名称应对应于Sizzle.selectors.find和Sizzle.selectors.filter对象中指定的名称。
1.查找
为了添加一个新的查找函数:
必须将正则表达式添加到匹配对象中。
必须定义一个查找函数。
“|”+NAME必须附加到Sizzle.selectors.order正则表达式,代码如下:
Sizzle.selectors.find.NAME = function( match, context, isXML ) {}
这是一个在页面上查找某些元素的函数。每个选择器将指定的函数不超过一次。
该函数的参数说明如下:
match:是从指定的正则表达式与选择器匹配返回的结果数组。
context:指定查找的范围,即上下文DOMElement或DOMDocument。
isXML:布尔值,设置当前函数是否在XML文档中运行。
2.过滤
为了添加一个新的过滤语句:
必须将正则表达式添加到匹配对象中。
一个函数必须添加到过滤器对象。
可以将一个函数添加到preFilter对象(可选)。代码如下:
Sizzle.selectors.preFilter.NAME = function( match ) {}
这是一个可选的预过滤器函数,允许根据相应的正则表达式过滤匹配的数组,这将返回一个新的匹配数组。这个匹配的数组最终将被传递给过滤器函数。这是为了清理在过滤器函数中发生的一些重复处理。
Sizzle.selectors.filter.NAME: function( element, match[1][, match[2], match[3], …] ) {}
注意:match[0]被传递到过滤器之前将被删除,不能使用。
过滤方法的参数是元素和来自正则表达式的捕获对应于此过滤器(上面由匹配中指出的,从索引1开始)。返回结果必须为布尔值:如果元素与选择器匹配,则返回true,否则返回false。
3.属性
Sizzle.selectors.attrHandle.LOWERCASE_NAME = function(elem, casePreservedName, isXML) {}
处理需要专门处理的属性,如具有跨浏览器问题的href。返回结果必须是该属性的实际字符串值。
4.伪选择器
Sizzle.selectors.pseudos.NAME = function( elem ) {}
选择器引擎最常见的扩展:添加一个新的伪类。此函数的返回结果必须为布尔值:如果元素与选择器匹配,则返回true,否则返回false。
【示例1】这定义了一个简单的fixed伪类。
var $test = jQuery( document ); Sizzle.selectors.pseudos.fixed = function( elem ) { $test[ 0 ] = elem; return $test.css( "position" ) === "fixed"; };
当自定义伪选择器接收参数时,才需要使用createPseudo(function)函数。
Sizzle.selectors.createPseudo(function)
注意:在jQuery 1.8及更早版本中,用于创建具有参数的自定义伪类的API已被破坏。在jQuery 1.8.1+中,API向后兼容。无论如何,鼓励使用createPseudo()函数。
解析器编译包含其他函数的单个函数,具有参数的自定义伪选择器更清晰。
【示例2】在Sizzle中,执行:not( <sub-selector> )伪类类似如下代码。
为了编写具有可以利用新API的参数的自定义选择器,但仍支持所有版本的Sizzle,请检查createPseudo()函数。
【示例3】以下示例使用jQuery语法。
这些过滤器在选择器的上一部分已经返回结果之后运行。setFilters从匹配的Sizzle.selectors.match.POS中找到。使用时,参数预计为整数。not参数是一个布尔值,表示结果是否应该反转(如div:not(:first))。
【示例4】第一个setFilter的代码类。
很容易扩展Sizzle,甚至Sizzle的POS选择器。例如,要重命名“:first”为“:uno”。
Sizzle.selectors.match.POS = new RegExp( oldPOS.source.replace("first", "uno"), "gi" ); Sizzle.selectors.setFilters.uno = Sizzle.selectors.setFilters.first; delete Sizzle.selectors.setFilters.first; Sizzle("div:uno"); //==> [ <div> ]
3.2.9 内部API
一般功能应通过公共API和扩展API访问,内部API专门用于内部使用。
Sizzle内部缓存编译的选择器函数和标记化对象。这些缓存的长度默认为50,但可以通过分配给此属性设置为任何正整数。
Sizzle.selectors.cacheLength
下面编译一个选择器函数并缓存它以供以后使用。例如,在插件初始化期间调用Sizzle.compile(".myWidget: myPseudo")将加快匹配元素的第一选择。
Sizzle.compile( selector )
参数selector表示一个CSS选择器。最后返回一个函数,即在过滤可能匹配元素的集合时使用的编译函数。
3.2.10 Sizzle代码结构
Sizzle()构造函数包含了三十多个私有函数,Sizzle引擎正是通过这些功能函数完成CSS选择器字符串的分拣、匹配、过滤等操作,最终从文档中找出匹配的DOM元素,并返回这些元素。下面是jQuery框架中嵌入的Sizzle代码,主要结构如下: