日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

jQuery Sizzle选择器(一)

發布時間:2024/4/13 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 jQuery Sizzle选择器(一) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1、瀏覽器對css選擇器采取逆向(從右向左)解析的原因:

  如果正向解析,例如「div div p em」,我們首先就要檢查當前元素到 html 的整條路徑,找到最上層的div,再往下找,如果遇到不匹配就必須回到最上層那個 div,往下再去匹配選擇器中的第一個 div,回溯若干次才能確定匹配與否,效率很低。

  逆向匹配則不同,如果當前的 DOM 元素是 div,而不是 selector 最后的 em,那只要一步就能排除。只有在匹配時,才會不斷向上找父節點進行驗證。找到所有的em之后,再通過查找他的父元素是不是p來進行過濾。

2、Sizzle如果分解用戶傳入的css選擇器字符串

以”div > div.cl p span.red“為例

  在Sizzle內部封裝了一個方法,該方法負責將css選擇器分解為一個數組。數組中的每一項是一個對象,格式如下:

    {

      "type" : "CLASS",

      "value" : ".red",
      "matchs" : " "

    }

  看一下tokenize的源碼:

  // 假設傳入進來的選擇器是:div > p + .cl[type="checkbox"], #id:first-child
  // 這里可以分為兩個規則:div > p + .aaron[type="checkbox"] 以及 #id:first-child
  // 返回的需要是一個Token序列
  // Sizzle的Token格式如下 :{value:'匹配到的字符串', type:'對應的Token類型', matches:'正則匹配到的一個結構'}
  function tokenize( selector, parseOnly ) {
    var matched, match, tokens, type,
    soFar, groups, preFilters,
    cached = tokenCache[ selector + " " ];
    // 這里的soFar是表示目前還未分析的字符串剩余部分
    // groups表示目前已經匹配到的規則組,在這個例子里邊,groups的長度最后是2,存放的是每個規則對應的Token序列

    // 如果cache里邊有,直接拿出來即可
    if ( cached ) {
      return parseOnly ? 0 : cached.slice( 0 );
    }

    // 初始化
    soFar = selector;

    // 這是最后要返回的結果,一個二維數組

    // 有多少個并聯選擇器,里面就有多少個數組,數組里面是擁有value與type的對象
    groups = [];?

    // 這里的預處理器為了對匹配到的Token適當做一些調整
    // 自行查看源碼,其實就是正則匹配到的內容的一個預處理
    preFilters = Expr.preFilter;

    // 遞歸檢測字符串
    // 比如"div > p + .cl input[type="checkbox"]"
    while ( soFar ) {

      // ?以第一個逗號切割選擇符,然后去掉前面的部分,處理同時傳入多個同級選擇器的情況,例如:$( "div, span" )
      if ( !matched || (match = rcomma.exec( soFar )) ) {
        if ( match ) {
          // 如果匹配到逗號,將soFar中匹配到的部分刪除掉
          soFar = soFar.slice( match[0].length ) || soFar;
        }
        // 往規則組里邊壓入一個Token序列,目前Token序列還是空的
        groups.push( tokens = [] );
      }

      // 將matched重置為false,為下次判斷soFar中是否有內容做準備

      matched = false;

      // 將剛才前面的部分以關系選擇器再進行劃分
      // 先處理這幾個特殊的Token : >, +, 空格, ~
      // 因為他們比較簡單,并且是單字符的
      if ( (match = rcombinators.exec( soFar )) ) {
        // 獲取到匹配的字符
        matched = match.shift();
        // 放入Token序列中
        tokens.push({
          value: matched,
          type: match[0].replace( rtrim, " " )
        });
        // 剩余還未分析的字符串需要減去這段已經分析過的
        soFar = soFar.slice( matched.length );
      }

      // 這里開始分析這幾種Token : TAG, ID, CLASS, ATTR, CHILD, PSEUDO, NAME
      // 將每個選擇器組依次用ID,TAG,CLASS,ATTR,CHILD,PSEUDO這些正則進行匹配
      // Expr.filter里邊對應地 就有這些key
      //如果通過正則匹配到了Token格式:match = matchExpr[ type ].exec( soFar )
      //然后看看需不需要預處理:!preFilters[ type ]
      //如果需要 ,那么通過預處理器將匹配到的處理一下 : match = preFilters[ type ]( match )

      for ( type in Expr.filter ) {

        if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] ||
          (match = preFilters[ type ]( match ))) ) {
          matched = match.shift();
          //放入Token序列中
          tokens.push({
            value: matched,
            type: type,
            matches: match
        });
        //剩余還未分析的字符串需要減去這段已經分析過的
        soFar = soFar.slice( matched.length );
      }
    }

    //如果到了這里都還沒matched到,那么說明這個選擇器在這里有錯誤
    //直接中斷詞法分析過程
    //這就是Sizzle對詞法分析的異常處理
    if ( !matched ) {
      break;
    }
  }
  //放到tokenCache函數里進行緩存
  //如果只需要這個接口檢查選擇器的合法性,直接就返回soFar的剩余長度,倘若是大于零,說明選擇器不合法
  //其余情況,如果soFar長度大于零,拋出異常;否則把groups記錄在cache里邊并返回,
  return parseOnly ?
    soFar.length :
    soFar ?
    Sizzle.error( selector ) :
    tokenCache( selector, groups ).slice( 0 );
}

總結

以上是生活随笔為你收集整理的jQuery Sizzle选择器(一)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。