`
jljlpch
  • 浏览: 323961 次
  • 性别: 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,>这样的符合来选择:

 

 

 

分享到:
评论

相关推荐

    css-selector-httpbuilder-源码.rar

    1. **CSS选择器解析器**:这部分代码实现了对CSS选择器字符串的解析,将其转化为可执行的逻辑。通常会涉及词法分析(将选择器字符串拆分成令牌)和语法分析(根据CSS选择器语法规则生成解析树)。 2. **DOM操作接口...

    前端开源库-has-id-selector

    3. **性能分析**:在性能敏感的场景下,通过检查ID选择器,避免不必要的DOM遍历,可以提升页面渲染速度。 ### 结语 `has-id-selector`作为一个轻量级的前端工具,为开发者提供了一种高效的方式来处理CSS选择器中的...

    前端开源库-has-element-selector

    "has-element-selector"库的运作原理可能是通过遍历DOM树,应用给定的选择器到每个元素上,然后检查是否有任何匹配。这样的功能在很多场景下都很实用,比如: 1. **代码质量检查**:在开发过程中,确保所使用的CSS...

    dom4j 源码

    这个源码分析将深入探讨 dom4j 的核心概念、主要类和接口,以及它们在 XML 处理中的作用。 1. **基本概念** - **Document**: 在 dom4j 中,`Document` 类代表整个 XML 文档,它是所有元素和属性的根节点。 - **...

    jQuery源码分析-03构造jQuery对象

    通过对jQuery源码中关于构造jQuery对象部分的分析,我们可以了解到jQuery对象的构造流程以及不同`selector`类型的处理方式。同时,通过`jQuery.extend`和`jQuery.fn.extend`的使用,使得jQuery具有良好的扩展性和...

    JavaScript DOM 编程艺术

    1. **节点(Node)**:在 DOM 中,文档由一系列节点构成。包括元素节点、属性节点、文本节点等。 2. **文档对象(Document)**:代表整个 HTML 或 XML 文档的根节点。 3. **元素(Element)**:表示文档中的 HTML 元素或 ...

    Longest CSS Selector-crx插件

    1. **展示最长选择器**: 这个插件能够实时分析页面的CSS代码,并找出其中选择器路径最长的那个。这有助于开发者理解页面结构的复杂性,以及可能存在的优化空间。选择器路径越长,通常意味着更复杂的DOM匹配,可能会...

    Javascript Date Selector1

    总的来说,JavaScript Date Selector1是一个提高用户体验的实用工具,它结合了JavaScript的Date对象和DOM操作,创建了一个交互式的日期选择界面。通过学习和理解这个控件的工作原理,开发者可以为自己的项目构建更...

    Jquery源码分析 源码

    - **工厂函数**:$(selector)是jQuery的工厂函数,它接受字符串、DOM元素或jQuery对象,返回jQuery实例。 - **委托构造器**:jQuery构造函数可以接收一个DOM元素数组,创建出一个jQuery对象,实现了实例化的延迟...

    The js code of selector

    本文将深入探讨JavaScript选择器的原理,通过源码分析来提升对这一核心概念的理解。 首先,我们要理解什么是CSS选择器。CSS选择器是用于匹配HTML或XML文档中的元素的规则集。例如,`#myID`选择器匹配id为"myID"的...

    selector的使用

    通过分析和运行`DemoSelector`,我们可以更好地理解和实践选择器的用法。 总结来说,选择器是编程中一个基础但至关重要的工具,无论是在前端美化网页,还是在后端处理复杂的数据流,都发挥着不可或缺的作用。理解并...

    shoot-to-kill-css-selector-intent:射杀; CSS选择器意图

    最后,利用CSS性能分析工具(如Chrome DevTools的Audits或Autoprefixer的Calculation)可以帮助我们检查选择器的效率,并提供改进建议。通过持续优化,我们可以实现"射杀"的CSS选择器意图,让代码更高效,页面加载更...

    jQuery facebook表情符号插件特效源码.zip

    - 插件可能使用`$(selector).append()`或`.html()`方法将表情符号插入到指定的DOM元素中。 4. **事件处理** - 为了响应用户的输入,插件可能监听键盘事件,如`keyup`,当用户按下特定键时,展示对应的表情符号。 ...

    China-City-Selector:中国城市多级选择Jquery plugin

    通过查看和分析这些文件,开发者可以深入理解插件的工作原理,对其进行定制或者二次开发,以满足特定项目的需求。 总的来说,"China-City-Selector"是中国Web开发中的一个实用工具,它利用jQuery的便利性,为多级...

    基于jQuery Selector.js插件实现的联动下拉框表单美化效果源码.zip

    在前端开发中,表单是用户与网页交互的...通过对这些文件的理解和分析,开发者可以学习到如何使用jQuery和Selector.js实现联动下拉框,以及如何结合Ajax和CSS进行表单美化,这对于前端开发者来说是一份宝贵的实战经验。

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

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

    simplehtmldom Doc api帮助文档

    - `find(string $selector[, int $index])`:通过CSS选择器找到元素,如果设置了`$index`则返回第N个元素,否则返回一个元素数组。 DOM遍历相关的属性和方法包括: - `$e-&gt;children([int $index])`:返回第N个子...

    Jquery详解-源码分析

    1. **选择器引擎(Sizzle)**:jQuery的核心是它的选择器引擎Sizzle,它实现了CSS1到CSS3的选择器,使得开发者能够轻松地选取DOM元素。Sizzle使用正则表达式和DOM遍历来高效匹配元素。 2. **链式调用**:jQuery对象...

    jQuery源码分析(1.7)

    1. **源码结构**:jQuery的核心是一个函数,该函数接受一个文档对象模型(DOM)作为参数,并返回一个包含所有匹配元素的集合。这个函数被称为`jQuery`或`$`。 ```javascript function jQuery(selector, context) { ...

    jQuery源码分析-03构造jQuery对象-源码结构和核心函数

    在进行jQuery源码分析的过程中,我们了解到jQuery对象是通过内部函数`jQuery.fn.init`构造的,其方法和属性则通过原型链继承自`jQuery.fn`,这是jQuery能够提供丰富且灵活DOM操作方法的基石。通过这种方式,即使不...

Global site tag (gtag.js) - Google Analytics