怎么有效的从种子合集seed里面找到选择器指定的元素?这里sizzle引入了过滤器,其原理如下:
function addCombinator(elems) {
//代码右图所示
}
这里只做了2层过滤查找,但是这个原理其实就很明了从右到左取出对应的条件,然后通过浏览器给出的原生的API判断是否能取到对应的指判断从而筛选其结果。
过滤处理我们需要考虑的问题:
1 怎么有效的匹配这些选择器的最小判断单元,也就是通过词法分割出后的结果 2 如果处理层级选择器的判断问题
如上可见,过滤是通过一层一层往上回溯不断的循环去查找,这样虽然结果可以拿到,但是效率是非常低的。所以sizzle从1.8后采用了空间换时间的方式,通过把各种过滤器编译成闭包的函数,所以这个过程也可说是"编译函数"。
在Sizzle中过滤器 Expr.filter主要分6大类型
“ID”,“TAG”、“CLASS”、“ATTR”、“CHILD”、“PSEUDO”
ID的过滤器
Expr.filter["ID"] = function(id) {
var attrId = id.replace(runescape, funescape);
return function(elem) {
return elem.getAttribute("id") === attrId;
};
};
TAG类型的过滤器
"TAG": function(nodeNameSelector) {
var nodeName = nodeNameSelector.replace(runescape, funescape).toLowerCase();
return nodeNameSelector === "*" ?
function() {
return true;
} :
function(elem) {
return elem.nodeName && elem.nodeName.toLowerCase() === nodeName;
};
},
其实我们看过滤器的就是一个具体的判断方法,通过传递一个上下文元素,来判断是否存在,得到这一个布尔值,这样有效了缓存了重复的处理,来节约判断的过程,下章节就会提到的“函数编译”中具体集合使用。
<!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]"; 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>