`
jljlpch
  • 浏览: 319373 次
  • 性别: Icon_minigender_1
  • 来自: 南昌
社区版块
存档分类
最新评论

dom selector 分析--1

    博客分类:
  • Ext
阅读更多

Ext.DomQueryJquery Selector的分析

1、概述

JS的主要作用就是对Dom元素的操作。操作Dom元素的显示,怎么显示,如何显示等形式。在操作Dom 元素,首先就是取得Dom元素的引用。一般我们都会采用document.getElementById(id)通过指定的id来引用,还有一个常用的方法就是通过document.getElementsByTagName(tagName)来获得指定tagNameDom元素的集合。对于间接引用,我们可以通过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分成两类,一类是从根据给定的selectorDom树找到相关的元素节点放到结果集中来,第二类就是在结果集中进行判断该元素还满足下面的表达式呢?第一类是是选择(selector),第二类是筛选(filter)

这样一下,就可以把一个复合的selector表达式分解成以多个单selector的操作。如div#id就可以变成先找到div的元素,之后就判断其元素的id是否等于id,如果不等于就从结果集中删除掉。而对于div[id=’bar’]也是一样,可以看出div#iddiv[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 FE > F or E/FE + FE ~ 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选择器的所有元素。

à第二步:在这些元素中找到classfoo的元素。如果没有就根本不要去分析下面的字符。

à第三步:根据: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是怎么实现的吧。

 

2domQuery分析

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就可以搞定的,现在又要生成函数,又要缓存。肯定慢的。所以使用domQueryselect最好的是那些经常重用的且path比较复杂的。

Ext.DomQuery.compile(p)就是主要处理根据path而动态编译查询的函数。上一节,我们讲到getElementById可以得到根据id得到元素在,那么.class,> p这样的呢?在EXT.domQuery中,每种方法都有一种像getElementById的方法。采用get开头是选择,采用by开头是筛选。

首先我们要选择元素,根据tagName,>这样的符合来选择:

 

 

 

分享到:
评论

相关推荐

    在laravel中使用Symfony的Crawler组件分析HTML

    composer require symfony/dom-crawler composer require symfony/css-selector css-seelctor 是 css选择器,用css选择节点时一些函数会用到 手册里面使用的例子是 use Symfony\Component\DomCrawler\Crawler; $...

    jQuery遍历DOM节点操作之filter()方法详解

    本文实例分析了jQuery遍历DOM节点操作之filter()方法。分享给大家供大家参考,具体如下: .filter(selector) 此方法用于在匹配元素中按照选择器表达式进行筛选。 记住:使用此方法必须得传入选择器表达式参数,不然...

    @FindBy-crx插件

    语言:English 生成cssselector和selenium @findby是一个google chrome web扩展,为... 它更快,准确,并将节省大量时间在分析DOM并编写CSS选择器和XPath。 让我们停止编写自定义和复杂CSS选择器和XPath并开始生成!

    深入分析JQuery和JavaScript的异同

    ps:LZ觉得这个标题有点大了,超出了能力范围,不喜勿碰。目前只记录LZ能力范围内的,日后持续补充。... var dom1 = jq1.get(index) 或者 var dom1 = jq1.get()[index];  DOM转化为JQuery:  假设cr是

    jQuery 遍历- 关于closest() 的方法介绍以及与parents()的方法区别分析

    closest() 方法获得匹配选择器的第一个祖先元素,从当前元素开始沿 DOM 树向上。 语法: .closest(selector) 参数selector为字符串值,包含匹配元素的选择器表达式。 如果给定表示 DOM 元素集合的 jQuery 对象,....

    jQuery源码解读之hasClass()方法分析

    本文较为详细的分析了jQuery源码解读之hasClass()方法。分享给大家供大家参考。具体分析如下: 代码如下:jQuery.fn.extend({  hasClass: function( selector ) { ...//循环检查每一个DOM元素的类名  for

    jQuery数据缓存用法分析

    本文分析了jQuery数据缓存用法。分享给大家供大家参考。具体如下: 在jQuery的API帮助文档中,jQuery这样描述数据缓存的作用:用于在一个元素上存取数据而避免了循环引用的风险。 一、定义缓存数据 使用$(selector)....

    myjquery:jquery源码分析

    jQuery源码分析 前言 有时候我在想jQuery为什么可以直接$操作,可以拥有比原生js更便利的DOM操作,而且只要你想就可以直接链式操作下去 核心框架 揭开一万多行代码的jQuery核心代码: (function(window, undefined)...

    Web前端开发技术-Jquery元素操作作.pptx

    遍历元素:基本语法$(selector).each(function(index,?domEle)?{}); 该方法的参数是一个函数。这个函数将会在遍历时调用 在函数中,index参数是每个元素的索引号 domEle是每个DOM元素的对象(个元素调用一次不是...

    Jquery 1.9.1源码分析系列(十二)之筛选操作

     find接受一个参数表达式selector:选择器(字符串)、DOM元素(Element)、jQuery对象。分两种情况处理:  第一种,如果传入的参数是非字符串,则先通过jQuery选择器将selector查找出来,然后过滤出包含于当前jQuery...

    android学习文档

    1、Selector技术 36 2、Tosat显示消息提示框技术 36 3、Handler消息传递机制 36 4、Handler类的主要作用 37 六、Android实例 38 1、做多米播放器的特效 38 2、做时钟的特效 39 1. 涉及的知识 40 一、完成”时钟”...

    get-page:网页分析工具

    get-pageweb page analyze tool一组工具, 包括下载网页文本, 构建DOM, 根据CSS selector 查询DOM元素等流程.典型用法: public static void getList(String selector, String url) { InfoExtracter ie = new ...

    jQuery中wrapInner()方法用法实例

    具体分析如下: 此方法使用指定的HTML内容或元素将匹配的元素内容包裹起来。 语法一: 用指定的DOM元素去包裹匹配元素的内容。 代码如下:$(selector).wrapInner(elem) 参数列表: 参数 描述 elem 用于包裹目标...

    jQuery源码分析之init的详细介绍

    jQuery( selector [, context ] ) ,这是一个标准且常用法,selector 表示一个 css 选择器,这个选择器通常是一个字符串,#id 或者 .class 等,context 表示选择范围,即限定作用,可为 DOM,jQuery 对象。

    jQuery中get()方法用法实例

    具体分析如下: 此方法可以返回匹配集合中所有DOM元素的数组或者一个指定索引的DOM元素。 索引值是从0开始的。 说明:从上面的定义可以看出,此方法可以将jQuery对象转换成DOM对象。 语法结构一: 代码如下:$...

    jodd-lagarto:Java HTML解析器套件

    :house_with_garden: 网站: :red_heart_selector: 对于开发人员,由开发人员执行。 :lizard: 概述Lagarto Suite是用Java编写HTML / XML解析器系列。 它由以下库组成: LagartoParser是一种通用的快速,通用的基于...

    jQuery中clone()方法用法实例

    主要介绍了jQuery中clone()方法用法,实例分析了clone()方法的功能、定义及克隆匹配的DOM元素的使用技巧,需要的朋友可以参考下

    jQuery内容过滤选择器与子元素过滤选择器用法实例分析

    //div.mini是DOM元素集合,:contains('div')是过滤条件 二、:has(selector) 选择器::has(selector) 描述:匹配含有选择器所匹配的元素的元素 返回值:元素集合 示例: $(div.mini:has(p)) //div.

    各浏览器中querySelector和querySelectorAll的实现差异分析

    querySelector和querySelectorAll的参数须是符合 css selector 的字符串。不同的是querySelector返回的是一个对象,querySelectorAll返回的一个集合(NodeList)

    htmlParser:简单的 JavaScript HTML 解析器

    // now throw it at a selector engine*: $ ( dom ) . query ( 'p.test &gt; a br' ) ; * 针对的测试(巧合的是,它使用 htmlParser 为其文档增添趣味) 执照 麻省理工学院许可证 (MIT) 版权所有 (c) 2013 杰森米勒 ...

Global site tag (gtag.js) - Google Analytics