制作JavaScript选择器(2)查询链
上回实现了将选择器解析为令牌,下面就要实现轮子的核心:令牌转换为查询链。
在描述查询链之前先定义伪代码:
操作 | 解释 |
---|---|
getNode() | 获取全部节点 |
filterAncestor() | 过滤祖先节点 |
childNode() | 获取子节点 |
filterParent() | 过滤父节点 |
nextNode() | 获取后一个紧邻的兄弟节点 |
filterPrev() | 过滤前一个紧邻的兄弟节点 |
nextAllNode() | 获取后面的兄弟节点 |
filterFront() | 过滤前面的兄弟节点 |
uniqueNode() | 去除重复 |
简单的查询链有两种,即从左到右和从右到左。
从左到右:
- 对每一个选择器子组进行以下操作
- 解析最左边的简单选择器,getNode
- 如果右边还有剩余部分,则根据连接符不同,对当前结果使用 getNode、childNode、nextNode 和 nextAllNode 其中一个
- 重复第二步,并对每次结果使用 uniqueNode 去除重复,直到结束
- 合并每个子组的结果,然后 uniqueNode 去除重复
从右到左:
- 对每一个选择器子组进行以下操作
- 解析最右边的简单选择器,getNode
- 如果左边还有剩余部分,则根据连接符不同,继续使用 filterAncentor、filterParent、filterPrev 和 filterFront 中的一个,直到结束;
- 合并每个子组的结果,然后 uniqueNode 去除重复
上一篇文章提到我打算使用分部查询,具体的操作就是只对“>”、“+”、“~”这三个连接符使用从左到右查询,对“ ”连接符采用从右到左查询。
对选择器 "A B C > D E F ~ G H"来说,从左到右可以描述为:
context
.getNode(A)
.getNode(B).uniqueNode()
.getNode(C).uniqueNode()
.childNode(D).uniqueNode()
.getNode(E).uniqueNode()
.getNode(F).uniqueNode()
.nextNode(G).uniqueNode()
.getNode(H).uniqueNode();
从右到左为描述为:
context
.getNode(H)
.filterAncestor(G)
.filterPrev(F)
.filterAncestor(E)
.filterAncestor(D)
.filterParent(C)
.filterAncestor(B)
.filterAncestor(A);
我的计划描述为:
context
.getNode(C)
.filterAncestor(B)
.filterAncestor(A)
.childNode(D)
.getNode(F)
.filterAncestor(E)
.nextNode(G)
.getNode(H)
基于令牌的伪查询链生成器http://dishuostec.sinaapp.com/javascript/css_token/parse/
示例:
选择器 | 查询串 |
---|---|
* | context.getNode( < * > ) |
body div | context.getNode( < div > ).filterAncestor( < body > ) |
h1#title + div > p | context.getNode( < #title, h1 > ).childNode( < p > ) |
div p a | context.getNode( < a > ).filterAncestor( < div >,< p > ) |
div, p, a | unique( context.getNode( < div > ) , context.getNode( < p > ) , context.getNode( < a > ) ) |