7-7 Sizzle过滤器原理(上)
本节编程练习不计算学习进度,请电脑登录imooc.com操作

Sizzle过滤器原理(上)

怎么有效的从种子合集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;
    };
},

其实我们看过滤器的就是一个具体的判断方法,通过传递一个上下文元素,来判断是否存在,得到这一个布尔值,这样有效了缓存了重复的处理,来节约判断的过程,下章节就会提到的“函数编译”中具体集合使用。

任务

  1. <!DOCTYPE HTML>
  2. <html>
  3. <head>
  4. <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  5. <script src="http://code.jquery.com/jquery-latest.js"></script>
  6. <title></title>
  7. </head>
  8. <body>
  9.  
  10.  
  11. <button id="test1">过滤器原理</button>
  12.  
  13. <div id="text">
  14. <p>
  15. <input type="text" />
  16. </p>
  17. <div class="Aaron">
  18. <input type="checkbox" name="readme" />
  19. <input type="checkbox" name="ttt" />
  20. <input type="checkbox" name="aaa" />
  21. <p>Sizzle</p>
  22. </div>
  23. </div>
  24.  
  25.  
  26.  
  27. <script type="text/javascript">
  28.  
  29.  
  30. //种子合集
  31. var seed = document.querySelectorAll('input')
  32.  
  33. //选择器
  34. var selector = "div > div.Aaron [name=ttt]";
  35.  
  36.  
  37. function addCombinator(elems) {
  38. var elem;
  39. while ((elem = elems['parentNode'])) {
  40. if (elem.nodeType === 1) {
  41. return elem
  42. }
  43. }
  44. };
  45.  
  46.  
  47. $('#test1').click(function() {
  48. for (var i = 0; i < seed.length; i++) {
  49. var ele = seed[i];
  50. var name = ele.getAttribute('name');
  51. if (name === 'ttt') {
  52. ele = addCombinator(ele);
  53. if (ele.getAttribute('class') === 'Aaron') {
  54. $('body').append('正确选择到了.Aaron[name=ttt]')
  55. }
  56. }
  57. }
  58. })
  59.  
  60.  
  61.  
  62. </script>
  63.  
  64. </body>
  65. </html>
下一节