`
yiminghe
  • 浏览: 1431545 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

一种基于匹配回朔的 css3 选择器引擎实现

 
阅读更多

一种基于匹配回朔的 css3 选择器引擎实现

介绍

CSS 选择器是一种应用于 DOM 节点查找场景的特定微型语法, 本质上和正则表达式一样都是一种模式匹配语言,灵活使用可以方便得获取指定位置的节点集合。

目前 W3C 推荐标准为 Selectors Level 3 , 在 ie9+ 以及 firefox,chrome,mobile 等浏览器上原生有基本一致的实现,而在 ie 下则需要 使用 javascript 模拟实现,本文介绍一种基于匹配回朔的 css3 选择器引擎实现,特定应用于 ie6,7,8 下。

语法

css 选择器是一种紧凑的语法,根据 css3 规范一个选择器字符串首先由 ',' 号分割的组组成,例如

s = g1,g2

表示匹配 g1 与 g2 的元素集合。组内又由以 ' ','+','>','~' 分割的简单选择器序列组成,例如

g1 = simple1 + simple2
g1 = simple1  simple2
g1 = simple1 > simple2
g1 = simple1 ~ simple2

+ 表示 simple1 匹配的元素与 simple2 的在同一层级,且 simple2 的元素紧跟在 simple1 后面。

> 表示 simple2 匹配的元素紧跟在 simple1 的下一层级。

' ' 表示 simple1 匹配的元素比 simple2 的层级更靠近根节点。

~ 表示 simple1 匹配的元素与 simple2 的在同一层级,且位置靠前。

简单选择器序列又可以由类型选择器以及后缀选择器组成,例如

simple1 = type_selector suffix_selector

其中 typeselector 表示标签的名称,例如 'h1','h2'。不指定时默认为 '*' 表示匹配任何标签。 suffixselector 则一般用来进一步过滤,例如类选择器(限定类名),属性选择器(限定属性),伪类、伪元素等。

例如 h1.x 匹配 <h1 class='x'> 而不匹配 <h1><span class='x'>

完整语法描述可以查看 w3c 标准页面

以下文章为了简单描述,将这种语法抽象为

a.b + c.d ~ e.f

其中 a c e 为类型选择器,b d f 为后缀选择器,+ 代表直接位置关系的 > +,~ 代表模糊位置关系的 ~ ' '.

实现

解析器生成

首先把 css 选择器语法用 LALR 解析程序生成器生成解析程序,从而可以把选择器的字符串格式转换成结构化的数据。 这里采用 kison 来生成。

对应 css 选择器语法的 kison 格式描述为: selector-grammar

生成的解析器代码如下: parser.js

流程图如下:

解析器生成

解析后的结构化数据为双向链表格式,例如

a.b + c.d

解析后的链表为:

linkedlist

引擎查找

接下来的工作就是引擎查找,查找过程比较复杂,下面根据以下流程图结合实例讲解:

engine

举例选择器字符串为:

a.b + c.d ~ a + e.f

匹配节点串为:

e.f a.b c.d e c.d e a e.f

获取种子集合

和一般浏览器实现类似,采用自右向左的查找方法,首先要从最右端 的 type selector 获取到种子集合,根据本例为:

a e.f a.b c.d e c.d e a e.f
  ^           ^     ^   ^

选择器链表分组

将选择器根据直接位置进行分组,以直接位置相连的简单的选择器序列为一组,分组后

a.b + c.d    ~     a + e.f
---------          -------

分组的意义在于,每次匹配都以直接位置相连的组为单元做匹配,回朔时也应当以组为单元回朔(直接位置处回朔无意义)。

初步过滤种子

根据最后的一组的选择器序列:

a + e.f

进一步过滤种子集合,过滤后为:

a e.f a.b c.d e c.d e a e.f
  ^                     ^
  1                     2

进一步过滤种子

这一步会根据对种子进行进一步过滤,过滤过程中甚至会发生回朔。

例如对于第一个种子,在初步过滤后,节点串游标和选择器游标分别在

    a e.f a.b c.d e c.d e a e.f
   ^


    a.b + c.d    ~     a + e.f
            ^

由于节点串游标已经越过节点串头,则表明该次匹配失败,该种子节点匹配失败。

对于第二个种子,在初步过滤后,节点串游标和选择器游标分别在

        a e.f a.b c.d e c.d e a e.f
                            ^


        a.b + c.d    ~     a + e.f
                ^

由于匹配失败,但选择器链接为 '~' ,则可不移动选择器游标,而只移动节点串游标:

        a e.f a.b c.d e c.d e a e.f
                          ^


        a.b + c.d    ~     a + e.f
                ^

可继续匹配到:

        a e.f a.b c.d e c.d e a e.f
                      ^


        a.b + c.d    ~     a + e.f
          ^

此时由于选择器链接为 '+' 因而移动节点串游标已经不可能再次匹配,此时应对选择器游标进行回朔到该分组前面:

        a e.f a.b c.d e c.d e a e.f
                      ^


        a.b + c.d    ~     a + e.f
                ^

此时仍然匹配不成功,但可以移动节点串游标为:

        a e.f a.b c.d e c.d e a e.f
                    ^


        a.b + c.d    ~     a + e.f
                ^

此时可以匹配选择器游标到头:

        a e.f a.b c.d e c.d e a e.f
          ^


        a.b + c.d    ~     a + e.f
       ^

则表明该种子节点符合本次选择器串,最终匹配节点个数为 1

        a e.f a.b c.d e c.d e a e.f
                                ^

引擎代码

引擎代码可参见: selector.js

单元测试

单元测试直接拉取 sizzle 对应于 css3 的部分,经过少量调整,全部通过:

selector - sizzle 测试

性能测试

kissy-selector-sizzle

欢迎提交新的例子。

分享到:
评论

相关推荐

    CSS3结构性伪类选择器九种写法

    child()用法实际上有三种变化,demo的用法是最简单的,X:nth-child()更强大的用处在于奇偶匹配,明河不展开讲,有兴趣的请看《Understanding :nth-child Pseudo-class Expressions》,《CSS3 :nth-child()伪类选择器...

    CSS选择器种类、优先级与匹配原理详解

    这个时候突然意识到了CSS选择器的优先级问题,这里就CSS选择器的优先级问题做了一些总结。 51CTO推荐阅读:巧妙地使用CSS选择器 选择器种类 严格来讲,选择器的种类可以分为三种:标签名选择器、类选择器和ID选择...

    css入门笔记

    2.css选择器 1.选择器的作用 规范页面中那些元素能够使用定义好的样式。 2.选择器详解 1.通用选择器 *{样式} 2.元素选择器 p{样式} 3.类选择器 1. 声明 .class名{样式} 2.引用可以引用多个类名用空格隔开...

    JavaScript实现自己的DOM选择器原理及代码

    解释器模式(Interpreter):定义一种语法格式,...匹配原理:浏览器在匹配CSS选择符时是按照从右到左匹配的,所以实现自己的DOM选择器时匹配行为也应该和浏览原生匹配行为一致。 代码: 代码如下: (function (ns) { /*

    详解CSS3中属性选择器新增加的特性

    零、概览CSS2支持的属性选择器用一个表达式[{属性 | 属性 {= | |= | ~=} 值}]1.[class=a]只能匹配class=a的元素2.[class~=a]则可以匹配class=a、class=a b的元素3.[lang|=en]则可以匹配lang=en、lang=en-us的元素。...

    jQuery 顺便学习下CSS选择器 奇偶匹配nth-child(even)

    对此,我把CSS3标准中nth-child()用法大致介绍下: CSS3伪类选择器:nth-child() 简单的归纳下nth-child()的几种用法。 第一:nth-child(number) 直接匹配第number个元素。参数number必须为大于0的整数。(EG) li:nth...

    举例详解CSS中的的优先级

    优先级是根据由每种选择器类型构成的级联字串计算而成的。他是一个对应匹配表达式的权重。 如果优先级相同,靠后的 CSS 会应用到元素上。 注意:元素在文档树中的位置是不会影响优先级的优先级顺序 优先级逐级增加的...

    CSS优先级的两种理解方式

    优先级就是分配给指定的 CSS 声明的一个权重,它由 匹配的选择器中的 每一种选择器类型的 数值 决定。 而当优先级与多个 CSS 声明中任意一个声明的优先级相等的时候,CSS 中最后的那个声明将会被应用到元素上。 当同...

    XPath CSS Explorer-crx插件

    找到针对任何元素的优化的XPath和CSS选择器,浏览/搜索CSS选择器 XPath CSS资源管理器此工具旨在为Web开发人员提供探索网页结构并生成优化且健壮的XPath和CSS选择器的功能,以便在他们的测试和其他用例中使用它们。 ...

    jQuery基本过滤选择器使用介绍

    简单过滤选择器是过滤选择器中使用最广泛的一种 jQuery选择器详解 根据所获取页面中元素的不同,可以将jQuery选择器分为:基本选择器、层次选择器、过滤选择器、表单选择器四大类。其中,在过滤选择器中有可以分为:...

    snabbdom-selector:Snabbdom虚拟节点CSS选择器

    snabbdom-selector是一种使用TypeScript编写的实用工具,用于查找与给定CSS选择器匹配的snabbdom VNode对象。 这是给我的! npm install snabbdom-selector 基本用法 import { select } from 'snabbdom-selector'...

    浏览器如何判断css优先级

    优先级是根据由每种选择器类型构成的级联字串计算而成的. 它不是一个对应相应匹配表达式的权重值. 如果优先级相同,元素最终会应用 CSS 中靠后的声明. 注意: 在文档树中的距离是不会对元素优先级计算产生影响的....

    ABBAdata CSS Selector Finder-crx插件

    一种简单,功能强大且交互式的方法,可为任何DOM元素查找唯一CSS选择器。 使用控制面板在任何页面元素上查找唯一CSS选择器,该面板在单击元素时会不断更新。 包含以下功能:-高度可定制CSS选择器生成:-启用/禁用ID...

    工程硕士学位论文 基于Android+HTML5的移动Web项目高效开发探究

    WebApp 基于浏览器来实现的一种应用 HybridApp 一种可以下载的Native App,其用户界面的全部或者部分元素在嵌入式浏览器组件(WebView之类的)里面运行 优雅降级 一开始就构建站点的完整功能,然后针对浏览器测试和...

    editplus 代码编辑器html c++ jsp css

    (1)选择“从行首开始匹配”,“查找内容”组合框中出现字符“^”,表示待查找字符串必须出现在文本中一行的行首。 (2)选择“字符在范围中”,那么在“^”后会增加一对括号“[]”,当前插入点在括号中。括号在...

    jQuery详细教程

    提示:jQuery 使用的语法是 XPath 与 CSS 选择器语法的组合。在本教程接下来的章节,您将学习到更多有关选择器的语法。 文档就绪函数 您也许已经注意到在我们的实例中的所有 jQuery 函数位于一个 document ready ...

    css:CSSLESS样式指南

    Celery CSS / LESS样式指南从Airbnb修改而来的一种最合理CSS和LESS方法目录----- - --订购-嵌套选择器 术语 规则声明“规则声明”是赋予选择器(或一组选择器)以及一组随附属性的名称。 这是一个例子: . listing {...

    搜索引擎代码

    3.后台的“广告点击记录”、“用户贡献列表”、“搜索日志列表”、“蜘蛛爬行列表”均增加“删除全部记录”的按钮,当数据库较大时可选择一次性清理这些数据。(重要) 4.对推广中心和后台管理界面的细节和样式进行...

    zencoding for Komodo

     使用仿CSS选择器的语法来快速开发HTML和CSS html+css 代码快速编写 ——由Sergey Chikuyonok开发。  Zen Coding由两个核心组件组成:一个缩写扩展器(缩写为像CSS一样的选择器)和上下文无关的HTML标签对匹配器。

Global site tag (gtag.js) - Google Analytics