Sizzle引擎--原理与实践(三)
查找的入口对应的是Sizzle.find方法,
Sizzle.find = function( expr, context) {}
expr :查找的表达式
context :查找的范围
find的步骤
第一步:判断主要集合,方法说过了,依次匹配,顺序就是ID --> NAME --> TAG
第二步:(1)当有类型被匹配时,调用相应的方法,获取集合set。(2)当ID,NAME,TAG全部不匹配时,获取context范围内的全部元素集合set
第三步:去除expr中已经匹配的部分,返回结果{expr : expr,set : set}
因此,Sizzle.find的大致代码流程是
Sizzle.find = function( expr, context, isXML ) { for ( i = 0, len = Expr.order.length; i < len; i++ ) { var type = Expr.order[i]; if((match = Expr.leftMatch[ type ].exec( expr ))){ // 对应第一步 if((set = Expr.find[ type ]( match, context ))!=null){ //对应第二步(1) expr = expr.replace( Expr.match[ 'ID' ], "" ); //对应第三步 break; } } } if(!set){//对应第二步(2) set = context.getElementsByTagName( "*" ); } return {expr : expr,set : set} }
实例说明:
<input type="radio" id="a" name="gender" value="man" class="default" /><label for="a" >男</label> <input type="radio" id="b" name="gender" value="man" class="default" /><label for="b">女</label> <input type="checkbox" id="c" name="gender" value="man" /><label for="c">人妖</label> var set; var expr = 'input[class*="default"]'; var match = Expr.leftMatch[ 'ID' ].exec( expr ) var left = match[1]; match.splice( 1, 1 ); set = Expr.find[ 'ID' ]( match, document); if ( set != null ) { expr = expr.replace( Expr.match[ 'ID' ], "" ); } if ( !set ) { set = typeof document.getElementsByTagName !== "undefined" ?document.getElementsByTagName( "*" ) :[]; } Expr.find['ID'] = function( match, context ) { if ( typeof context.getElementById !== "undefined") { var m = context.getElementById(match[1]); return m && m.parentNode ? [m] : []; } } console.log({ set: set, expr: expr });
因此从上面的实例来看,Sizzle.find并不是执行查找功能的部分,而是主要起了一个分发器的作用,
将不同的选择表达式分发到不同的更专一的查找器上面。上面的例子中就是将具体查找分发给Expr.find[ 'ID' ]
具体代码分析:
Sizzle.find = function( expr, context, isXML ) { var set, i, len, match, type, left; if ( !expr ) { //如果没有选择表达式,直接返回空集合 return []; } for ( i = 0, len = Expr.order.length; i < len; i++ ) {//用来判断应该选用哪个查找器,对应的顺序是[ "ID", "NAME", "TAG" ]; type = Expr.order[i]; if ( (match = Expr.leftMatch[ type ].exec( expr )) ) { //碰到符合条件的匹配 left = match[1]; match.splice( 1, 1 ); //因为leftMatch在match的头部添加了一个新的分组,所以现在提取第一个分组到left里面,然后删除这个分组 if ( left.substr( left.length - 1 ) !== "\\" ) { //参见讨论部分 match[1] = (match[1] || "").replace( rBackslash, "" ); \\检测,替换回车而已 set = Expr.find[ type ]( match, context, isXML ); \\转到相应的查找器执行查找程序 if ( set != null ) { //找到相应的结果,修剪expr expr = expr.replace( Expr.match[ type ], "" ); break; } } } } if ( !set ) { //[ "ID", "NAME", "TAG" ]中没有匹配的类型时候,直接返回context范围内的所有标签。 set = typeof context.getElementsByTagName !== "undefined" ? context.getElementsByTagName( "*" ) :[]; } return { set: set, expr: expr }; }; Expr.order = [ "ID", "NAME", "TAG" ]; Expr.find = { ID: function( match, context, isXML ) { if ( typeof context.getElementById !== "undefined" && !isXML ) { var m = context.getElementById(match[1]); return m && m.parentNode ? [m] : []; //这里注意优先级的问题。&&的优先级高于?:的优先级 } }, NAME: function( match, context ) { if ( typeof context.getElementsByName !== "undefined" ) { var ret = [], results = context.getElementsByName( match[1] ); for ( var i = 0, l = results.length; i < l; i++ ) { if ( results[i].getAttribute("name") === match[1] ) { ret.push( results[i] ); } } return ret.length === 0 ? null : ret; } }, TAG: function( match, context ) { if ( typeof context.getElementsByTagName !== "undefined" ) { return context.getElementsByTagName( match[1] ); } } };
讨论
1、关于检测'\'的讨论【这个不知道对不对】
实例表达式expr = '\.className',CLASS匹配结果['\.className','.className'],此时原本的意图是'.'被转义,因此不应该作为class匹配,中止。
2、关于getElementById方法bug的讨论(源码1056行),
在某些浏览器里面,getElementById('test')会返回name值为test的a节点,因此会对查询结果产生干扰。比如:
<a name="test"></a><div id="test"></div>此时a节点在div前面,getElementById('test')回返回<a name="test"></a>而非预期中的<div id="test"></div>。
Sizzle也对此做了检测:
(function(){ // 先创建一个测试环境<div><a name="script20120215"></a></div> var form = document.createElement("div"), id = "script" + (new Date()).getTime(), root = document.documentElement; form.innerHTML = "<a name='" + id + "'/>"; root.insertBefore( form, root.firstChild ); //检测getElementById的返回值,现获取了相应的节点之后,添加一步检测id属性,如果吻合就保存,不吻合就丢弃
if ( document.getElementById( id ) ) { Expr.find.ID = function( match, context, isXML ) { if ( typeof context.getElementById !== "undefined" && !isXML ) { var m = context.getElementById(match[1]); return m ? m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ? [m] : undefined : []; } };
Expr.filter.ID = function( elem, match ) { var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id"); return elem.nodeType === 1 && node && node.nodeValue === match; }; } root.removeChild( form ); // 对于IE,需要释放刚才添加的DIV过程中各变量的缓存,便于垃圾回收 root = form = null; })();
相关推荐
资源分类:Python库 所属语言:Python 资源全名:ws_sizzle-0.0.4-py3-none-any.whl 资源来源:官方 安装方法:https://lanzao.blog.csdn.net/article/details/101784059
Sizzle 开发环境 一个 /g/ 用户将 OpenNT NTOSBE 构建环境移植到 Win2003 源,作为源中包含的 razzle 构建环境的替代品。 目前它可以很好地构建源代码,但用户注意到了...上次指南更新的最新版本: Sizzle-devtest.7z
python库,解压后可用。 资源全名:sphinx_sizzle_theme-0.0.8-py2.py3-none-any.whl
资源来自pypi官网。 资源全名:sphinx_sizzle_theme-0.0.8-py2.py3-none-any.whl
在 http://www.cnblogs.com/strick/p/5078435.html 有描述
Sizzle: A Standards-based end-to-end Security ArchitectureSizzle: A Standards-based end-to-end Security ArchitectureSizzle: A Standards-based end-to-end Security Architecture
在分析Sizzle源码之前,先整理一下选择器的工作原理,先明确一些选择器中用到的名词,后边阅读时不会有歧义
前端项目-sizzle,一个纯粹的JavaScript、自下而上的CSS选择器引擎,设计为可以轻松地放到主机库中。
sizzle-landing-page:菜品审查应用程序的纯HTML登陆页面
也许安装 ruby 的更好方法是通过 如果您还没有安装 在您的项目根目录中运行: $ 捆绑安装用法安装generator-sizzle-jekyll : npm install -g generator-sizzle-jekyll创建一个新目录,然后cd进入: mkdir my-...
在 http://www.cnblogs.com/strick/p/5078435.html 描述
Windows物联网开发开始风靡一时–了解通用Windows平台 “ Windows物联网开发的热潮–学习通用Windows平台”演示文稿的源代码 随时向我发的评论,反馈或问题。
于是看了jquery的源码,jquery用的选择器的引擎是sizzle,是jquery的作者另一开源项目,在github上面有,号称最快的dom选择器!不到2000行代码。上面说了不是很精彩的开场白,我么来个 for example: $(‘.test’) 在...
jQuery / Sizzle自定义伪选择器 只是我的伪装收藏。 表现 请注意将通过这些选择器传递多少个元素,因为它们将无法利用本机DOM querySelectorAll()方法提供的性能提升。 为了在使用这些伪指令中的任何一个时获得最佳...
NULL 博文链接:https://wubinclat.iteye.com/blog/471850
Sizzle 是一套前端用智能来处理模块和组件依赖关系的框架。 它遵循 CommonJS 的运行规范来完成对各个模块的动态加载。而且可以同时包含其他库而不产生冲突。 Sizzle的使用很简单,其下共有 5 个常用的方法, 只...
Sizzle,是jQuery作者John Resig写的DOM选择器引擎,速度号称业界第一。作为一个独立全新的选择器引擎,出现在jQuery 1.3版本之后,并被John Resig作为一个开源的项目。Sizzle是独立的一部分,不依赖任何库,如果你...
犀利开发_jQuery内核详解与实践(完整版421页).part2和犀利开发_jQuery内核详解与实践(完整版421页).part3;请下载到同一目录后,再解压。 二、本书说明: 本书循序渐进地讲解了jquery高效开发的方法和技巧,...