除了判断的过程,那么还涉及到节点的关系处理,如:
var selector = "div > div.Aaron [name=ttt]";
节点与节点之间是有层级关系的,这里就遇到了“>”与“空”。子元素组合器(E > F)和(E F)都作为后代组合,但是他们有所不同,更具体的是(E > F)它只会选择第一级的后代,那么我们从右边往左边匹配就会遇到这样的情况,[name=ttt]节点与div.Aaron中间的连接符“空”则为后代选择器,那么意味着[name=ttt]元素的可能是div.Aaron元素的一个孩子,孙子,曾孙等。
同理div.Aaron与div的连接符是“>” 子元素选择器,这个简单只能是父子关系。除此之外,还有相邻兄弟选择器“+”与“~”,(prev + next) 和 (prev ~ siblings)之间最值得注意的不同点是他们各自的可及之范围。前者只达到紧随的同级元素,后者扩展了该达到跟随其的所有同级元素。
针对选择器的层级关系:
首先“>”与“空”是祖辈关系,这样可以理解是线型的,那么我们只要递归检测每次元素的 parentNode 属性返回指定节点的父节点。
同理“+”与“~”也是类似的兄弟关系,无非就是扩展的范围不同,所以针对层级的关系问题。
jQuery引入了词素关系:
relative: { ">": { dir: "parentNode", first: true }, " ": { dir: "parentNode" }, "+": { dir: "previousSibling", first: true }, "~": { dir: "previousSibling" } }
这里的dir可以认为是查找的一个条件,就是查找父节点还是兄弟节点,那么first的意思就是一个快速条件,因为“>”选择器是一个很明确的父子关系所以通过标记first只需要查找一层即可。我们可以看代码:
function addCombinator(elems) { var elem; while ((elem = elems['parentNode'])) { if (elem.nodeType === 1) { return elem } } };
<!DOCTYPE HTML> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <script src="http://code.jquery.com/jquery-latest.js"></script> <title></title> </head> <body> <button id="test1">过滤器原理</button> <div id="text"> <p> <input type="text" /> </p> <div class="Aaron"> <input type="checkbox" name="readme" /> <input type="checkbox" name="ttt" /> <input type="checkbox" name="aaa" /> <p>Sizzle</p> </div> </div> <script type="text/javascript"> //种子合集 var seed = document.querySelectorAll('input') //选择器 var selector = "div > div.Aaron [name=ttt]"; var relative = { ">": { dir: "parentNode", first: true }, " ": { dir: "parentNode" }, "+": { dir: "previousSibling", first: true }, "~": { dir: "previousSibling" } } function addCombinator(elems) { var elem; while ((elem = elems['parentNode'])) { if (elem.nodeType === 1) { return elem } } }; $('#test1').click(function() { for (var i = 0; i < seed.length; i++) { var ele = seed[i]; var name = ele.getAttribute('name'); if (name === 'ttt') { ele = addCombinator(ele); if (ele.getAttribute('class') === 'Aaron') { $('body').append('正确选择到了.Aaron[name=ttt]') } } } }) </script> </body> </html>