Ext.DomQuery和Jquery Selector的分析
1、概述
JS的主要作用就是对Dom元素的操作。操作Dom元素的显示,怎么显示,如何显示等形式。在操作Dom 元素,首先就是取得Dom元素的引用。一般我们都会采用document.getElementById(id)通过指定的id来引用,还有一个常用的方法就是通过document.getElementsByTagName(tagName)来获得指定tagName的Dom元素的集合。对于间接引用,我们可以通过Dom元素的以下的几个方法parentNode,firstChild,lastChild,childNodes,nextSibling,previousSibling得到与本元素相关的Dom元素。
Js开发工具很简陋,没有提示,这些方法名太长,很容易写错,调试又很麻烦。Prototype的$(id)的出现,一下子似乎成为取得元素的标准。这是在知道元素的id的情况下,很多时候我们是不知道id的,比如我想找一个 name为’username’的input类型的元素?怎么办?
在写css时候,我们发现Css的对元素的选择是一个很好的解决方法,于是Js中对元素的查询现在都支持CSS1~CSS3的标准。那么如何去实现CSS选择器呢?http://www.w3.org/TR/2005/WD-css3-selectors-20051215/,是我们可以粗略分成几类,ID选择器(#id),Class选择器(.class),类型(type)选择器(p),Combinators,属性(Attribute)选择器,Pseudo Classes选择器等。这些都是单一的选择器,可以在应用中把它们组合起来,如:div#id, div:last-child。
我们仔细分析一下,这些选择器。既然叫做selector,肯定是有选择的功能。先分析一个例子:span[class=’test’],这是一个属性选择器,我们一般这样理解,找到class=’test’的所有标签为span的元素集。这就是从Dom树中select到所需要的元素。其实我们把这个拆分成两步,第一步是根据document.getElementsByTagName(tagName)取得span的元素集,第二步是再根据其class是否等于test来进行判断,把不等于的元素从结果集中去掉。事实上,扩展javascript只能是这样进行处理。
这样处理的话,我们就能把selector分成两类,一类是从根据给定的selector从Dom树找到相关的元素节点放到结果集中来,第二类就是在结果集中进行判断该元素还满足下面的表达式呢?第一类是是选择(selector),第二类是筛选(filter)。
这样一下,就可以把一个复合的selector表达式分解成以多个单selector的操作。如div#id就可以变成先找到div的元素,之后就判断其元素的id是否等于id,如果不等于就从结果集中删除掉。而对于div[id=’bar’]也是一样,可以看出div#id与div[id=’id’]是一样的操作。对于div.class也可以转换到属性中去操作。
我们可细化一下:把ID选择器(#id),Class选择器(.class),类型(type)选择器(p),Combinators,属性(Attribute)选择器,Pseudo Classes选择器等分成选择和筛选。Id Seletor在起始的位置,如#id,是选择器,不在起始的位置上如div#id是筛选器。Class选择器(.class)如ID选择器一样。属性(Attribute)选择器是筛选的功能。它只能在一个元素或多个元素后面。
对于Pseudo Classes选择器,其作用也是筛选的功能。(不过有的时候可能会是选择功能)。对于Type选择器,只能是选择器了,它要么是开始。要么和+,>,~组成复合的Combinators选择器。对于像E F,E > F or E/F,E + F,E ~ F这样的复合选择器,我们其三部分可以分成这样:E 是元素的集合,符号是>,+,~。而F只能是标签的形式了。a > p#id。这样分析的话,就是先取a > p所有元素的集合,再在集合找到id相同的。在分析的时候,对于p来说,他根本不要关心a,它只要关心于 >。我们可以把 > p看成和p相同的一部分,看成.class,#id这样的一部分。
看一个:div.foo:nth-child(odd)[@foo=bar]#aId > a
à第一步:找到div type选择器的所有元素。
à第二步:在这些元素中找到class为foo的元素。如果没有就根本不要去分析下面的字符。
à第三步:根据:nth-child(odd)找到元素的子孩子元素为偶数的的元素。进一步筛选了。
à第四步:找到[],就是属性筛选器了,根据foo属性值bar来判断集合中还有那些满足条件。
à第五步:在这些元素集合,找到id=aId的元素,进一步筛选。
à第六步:在这些元素集合中找到所有元素对应的子元素类型为a的所有子元素。
à结果:我们可以看到,现在元素是子元素的集合。
那么应该怎么分析这样的表达式呢?对div,可以采用getElementsByTagName,对于.foo,那我们得自己去写函数判断元素的是不是有这个class了,对于:nth-child(odd),我们也得采用Pseudo Classes的方法,对于[@foo=bar]我们也要写属性分析函数,对于#aId,采用getElementById。对于> a 我们也得自己来处理。如果.foo在开头怎么办?我们可能分成两步来做,先根据.在doucument中找到所有的元素,之后根据.foo进行筛选。
分隔这些字符串也不难,只要.,#,:,[, blackspace,+,/,>,~是分隔符。,+,/,>,~只要不在[]中出现就是元素选择器,在[]中出现是属性的比较器。
待续
看一下domQuery,Jquery是怎么实现的吧。
2、domQuery分析
select : function(path, root, type) { // 默认把document当做root if (!root || root == document) { root = document; } // 支持root采用string id的形式 if (typeof root == "string") { root = document.getElementById(root); } // 支持多个path var paths = path.split(","); var results = []; for (var i = 0, len = paths.length;i < len; i++) { // 去string前后的空格 var p = paths[i].replace(trimRe, ""); // cache 已经编译的select if (!cache[p]) { // 编译 cache[p] = Ext.DomQuery.compile(p); if (!cache[p]) { throw p + " is not a valid selector"; } } // 运行编译的函数 var result = cache[p](root); if (result && result != document) { results = results.concat(result); } } // 去掉重复的元素 if (paths.length > 1) { return nodup(results); } return results; },
在上面的代码中,我们可以看出该函数支持多个path, compile每个path之后,运行编译的函数。最后去掉重复的元素。上面的代码Ext.DomQuery.compile(p)是把每个path编译成函数,便于重用。这种方式对于较复杂的path是能提高效率的,但是如#id,.class的之类的,就得不偿失了。这应该是大量使用的,很多是用过之后又不用了。本来只要一些getElementById就可以搞定的,现在又要生成函数,又要缓存。肯定慢的。所以使用domQuery的select最好的是那些经常重用的且path比较复杂的。
Ext.DomQuery.compile(p)就是主要处理根据path而动态编译查询的函数。上一节,我们讲到getElementById可以得到根据id得到元素在,那么.class,> p这样的呢?在EXT.domQuery中,每种方法都有一种像getElementById的方法。采用get开头是选择,采用by开头是筛选。
首先我们要选择元素,根据tagName,>这样的符合来选择:
分享到:
相关推荐
composer require symfony/dom-crawler composer require symfony/css-selector css-seelctor 是 css选择器,用css选择节点时一些函数会用到 手册里面使用的例子是 use Symfony\Component\DomCrawler\Crawler; $...
本文实例分析了jQuery遍历DOM节点操作之filter()方法。分享给大家供大家参考,具体如下: .filter(selector) 此方法用于在匹配元素中按照选择器表达式进行筛选。 记住:使用此方法必须得传入选择器表达式参数,不然...
语言:English 生成cssselector和selenium @findby是一个google chrome web扩展,为... 它更快,准确,并将节省大量时间在分析DOM并编写CSS选择器和XPath。 让我们停止编写自定义和复杂CSS选择器和XPath并开始生成!
ps:LZ觉得这个标题有点大了,超出了能力范围,不喜勿碰。目前只记录LZ能力范围内的,日后持续补充。... var dom1 = jq1.get(index) 或者 var dom1 = jq1.get()[index]; DOM转化为JQuery: 假设cr是
closest() 方法获得匹配选择器的第一个祖先元素,从当前元素开始沿 DOM 树向上。 语法: .closest(selector) 参数selector为字符串值,包含匹配元素的选择器表达式。 如果给定表示 DOM 元素集合的 jQuery 对象,....
本文较为详细的分析了jQuery源码解读之hasClass()方法。分享给大家供大家参考。具体分析如下: 代码如下:jQuery.fn.extend({ hasClass: function( selector ) { ...//循环检查每一个DOM元素的类名 for
本文分析了jQuery数据缓存用法。分享给大家供大家参考。具体如下: 在jQuery的API帮助文档中,jQuery这样描述数据缓存的作用:用于在一个元素上存取数据而避免了循环引用的风险。 一、定义缓存数据 使用$(selector)....
jQuery源码分析 前言 有时候我在想jQuery为什么可以直接$操作,可以拥有比原生js更便利的DOM操作,而且只要你想就可以直接链式操作下去 核心框架 揭开一万多行代码的jQuery核心代码: (function(window, undefined)...
遍历元素:基本语法$(selector).each(function(index,?domEle)?{}); 该方法的参数是一个函数。这个函数将会在遍历时调用 在函数中,index参数是每个元素的索引号 domEle是每个DOM元素的对象(个元素调用一次不是...
find接受一个参数表达式selector:选择器(字符串)、DOM元素(Element)、jQuery对象。分两种情况处理: 第一种,如果传入的参数是非字符串,则先通过jQuery选择器将selector查找出来,然后过滤出包含于当前jQuery...
1、Selector技术 36 2、Tosat显示消息提示框技术 36 3、Handler消息传递机制 36 4、Handler类的主要作用 37 六、Android实例 38 1、做多米播放器的特效 38 2、做时钟的特效 39 1. 涉及的知识 40 一、完成”时钟”...
get-pageweb page analyze tool一组工具, 包括下载网页文本, 构建DOM, 根据CSS selector 查询DOM元素等流程.典型用法: public static void getList(String selector, String url) { InfoExtracter ie = new ...
具体分析如下: 此方法使用指定的HTML内容或元素将匹配的元素内容包裹起来。 语法一: 用指定的DOM元素去包裹匹配元素的内容。 代码如下:$(selector).wrapInner(elem) 参数列表: 参数 描述 elem 用于包裹目标...
jQuery( selector [, context ] ) ,这是一个标准且常用法,selector 表示一个 css 选择器,这个选择器通常是一个字符串,#id 或者 .class 等,context 表示选择范围,即限定作用,可为 DOM,jQuery 对象。
具体分析如下: 此方法可以返回匹配集合中所有DOM元素的数组或者一个指定索引的DOM元素。 索引值是从0开始的。 说明:从上面的定义可以看出,此方法可以将jQuery对象转换成DOM对象。 语法结构一: 代码如下:$...
:house_with_garden: 网站: :red_heart_selector: 对于开发人员,由开发人员执行。 :lizard: 概述Lagarto Suite是用Java编写HTML / XML解析器系列。 它由以下库组成: LagartoParser是一种通用的快速,通用的基于...
主要介绍了jQuery中clone()方法用法,实例分析了clone()方法的功能、定义及克隆匹配的DOM元素的使用技巧,需要的朋友可以参考下
//div.mini是DOM元素集合,:contains('div')是过滤条件 二、:has(selector) 选择器::has(selector) 描述:匹配含有选择器所匹配的元素的元素 返回值:元素集合 示例: $(div.mini:has(p)) //div.
querySelector和querySelectorAll的参数须是符合 css selector 的字符串。不同的是querySelector返回的是一个对象,querySelectorAll返回的一个集合(NodeList)
// now throw it at a selector engine*: $ ( dom ) . query ( 'p.test > a br' ) ; * 针对的测试(巧合的是,它使用 htmlParser 为其文档增添趣味) 执照 麻省理工学院许可证 (MIT) 版权所有 (c) 2013 杰森米勒 ...