zoukankan      html  css  js  c++  java
  • Sizzle一步步实现所有功能(一)

    前提:

    1.HTML5自带querySelectAll可以完全替代Sizlle,所以我们下面写的Sizzle,是不考虑QSA的。

    2.作者考虑了大量兼容情况,比如黑莓4.6系统这样几乎接触不到的bug。这样学习价值不高却很费时间问题我不去考虑。主要考虑IE8,这也是Sizzle没被淘汰的最主要原因。

    3.我喜欢采用var 声明每个变量,而不是一个var 声明好多变量。原因是我在一步步完善模仿的Sizzle,会有大量的修改。

    4.Sizzle的原理实际很简单,真的就可以这样一句话遍历页面所有元素,对每个元素进行排除,符合的则插入到结果数组。但功能繁多,层级繁杂,难点是架构。

    5.这是一篇超长的文章。

    第一步:实现Sizzle('#ID),Sizzle("TAG"),Sizzle(".CLASS")

     1 (function( window ){
     2     
     3 var arr = [];
     4 var select ;
     5 var push = arr.push;
     6 // http://www.w3.org/TR/css3-selectors/#whitespace
     7 // 各种空白待穿正则字符串
     8 var whitespace = "[\x20\t\r\n\f]";
     9 // 带空格选择器正则,记忆无空格选择器
    10 var rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\])(?:\\.)*)" + whitespace + "+$", "g" );
    11 // 快速选择器正则 ID 或者 TAG(包括*) 或者 CLASS 选择器
    12 var rquickExpr = /^(?:#([w-]+)|(w+|*)|.([w-]+))$/;
    13 
    14 // 浏览器代码正则
    15 var rnative = /^[^{]+{s*[native w/;30 // 入口
    31 function Sizzle( selector ){
    32     // 清除空格
    33     selector = selector.replace( rtrim, "$1" )
    34     var results = [];
    35     var match;
    36     var matcher;
    37     var elem;
    38     var m;
    39     var context = document;
    40     
    41     // 是否为最简选择器
    42     if( match = rquickExpr.exec( selector )){
    43         // Sizzle('#ID)
    44         if ( (m = match[1]) ) {
    45             elem = context.getElementById( m );
    46             if( elem ){
    47                 results.push( elem );
    48             }
    49             return results;
    50             
    51         // Sizzle("TAG")
    52         }else if( (m = match[2]) ){
    53             push.apply( results, context.getElementsByTagName( selector ) );
    54             return results;
    55         
    56         // Sizzle(".CLASS")    
    57         }else if( (m = match[3]) ){
    58             // 支持getElementsByClassName
    59             if( support.getElementsByClassName ){
    60                 push.apply( results, context.getElementsByClassName( m ) );
    61                 return results;
    62                 
    63             // 不支持getElementsByClassName
    64             }else {
    65                 // 获取遍历所有元素
    66                 // 如果元素类名与我们选择器匹配的类名相同,则插入到结果数组中
    67                 var elems = document.getElementsByTagName('*');
    68                 var pattern = new RegExp(selector.slice(1));
    69                 for(var i = 0; i<elems.length; i++) {
    70                     if(pattern.test(elems[i].className)){
    71                         results.push(elems[i])
    72                     }
    73                 }
    74             }
    75         }
    76     }
    77     return results;
    78 }
    79 // 版本支持变量的对外访问入口
    80 var support = Sizzle.support = {};
    81 
    82 // 判断是否支持getElementsByClassName
    83 // 支持: IE<9
    84 support.getElementsByClassName = rnative.test( document.getElementsByClassName );
    85 
    86 // 对外入口
    87 window.MSizzle = Sizzle;
    88 
    89 })(window)
    90 console.log(MSizzle("#id"))
    91 console.log(MSizzle(".class"))
    92 console.log(MSizzle("div"))

     1.rquickExpr.exec( selector )返回一个数组,exec方法返回一个数组,第0项是匹配的内容,第1项是第一个括号中记忆的内容,第2项是第一个括号中记忆的内容,依次类推。

    console.log(/(1)|(2)|(3)/.exec('1')); //[ "1", "1", undefined, undefined ] 
    console.log(/(1)|(2)|(3)/.exec('2')); //[ "2", undefined, "2", undefined ] 
    console.log(/(1)|(2)|(3)/.exec('3')); //[ "3", undefined, undefined, "3" ]

    2.判断浏览器是否支持某段代码的正则rnative = /^[^{]+{s*[native w/

  • 相关阅读:
    Leetcode888. 公平的糖果棒交换
    Leetcode81. 搜索旋转排序数组 II
    Leetcode80. 删除排序数组中的重复项 II
    Leetcode1631. 最小体力消耗路径
    Leetcode57. 插入区间
    Leetcode724. 寻找数组的中心索引
    Leetcode18. 四数之和
    Leetcode110. 平衡二叉树
    Leetcode1128. 等价多米诺骨牌对的数量
    python 集合和深浅copy
  • 原文地址:https://www.cnblogs.com/winderby/p/4195861.html
Copyright © 2011-2022 走看看