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

Sizzle过滤器原理(下)

除了判断的过程,那么还涉及到节点的关系处理,如:

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
               }
        }
};

任务

  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. var relative = {
  38. ">": {
  39. dir: "parentNode",
  40. first: true
  41. },
  42. " ": {
  43. dir: "parentNode"
  44. },
  45. "+": {
  46. dir: "previousSibling",
  47. first: true
  48. },
  49. "~": {
  50. dir: "previousSibling"
  51. }
  52. }
  53.  
  54.  
  55. function addCombinator(elems) {
  56. var elem;
  57. while ((elem = elems['parentNode'])) {
  58. if (elem.nodeType === 1) {
  59. return elem
  60. }
  61. }
  62. };
  63.  
  64.  
  65. $('#test1').click(function() {
  66. for (var i = 0; i < seed.length; i++) {
  67. var ele = seed[i];
  68. var name = ele.getAttribute('name');
  69. if (name === 'ttt') {
  70. ele = addCombinator(ele);
  71. if (ele.getAttribute('class') === 'Aaron') {
  72. $('body').append('正确选择到了.Aaron[name=ttt]')
  73. }
  74. }
  75. }
  76. })
  77.  
  78.  
  79.  
  80. </script>
  81.  
  82. </body>
  83. </html>
下一节