• sizzle源码分析 (2)ID 类 tag querySelectorAll 快速匹配


    不是所有的选择器都需要去分词,生成相应的匹配函数,这样流程比较复杂,当浏览器具备原生的方法去匹配元素是,没有理由不优先匹配,下面看看进入Sizzle后,它是怎么优先匹配这些元素的:

     
    function Sizzle( selector, context, results, seed ) {
        /*
        执行$("ul.list>li span:eq(1)")时,递归第二次时,
        selector
        "ul.list>li span"
    
        */
        var match, elem, m, nodeType,
            // QSA vars
            i, groups, old, nid, newContext, newSelector;
    
        if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) {
            setDocument( context );
        }
    
        context = context || document;
        results = results || [];
    
        if ( !selector || typeof selector !== "string" ) {
            return results;
        }
    
        if ( (nodeType = context.nodeType) !== 1 && nodeType !== 9 ) {
            return [];
        }
    
        if ( documentIsHTML && !seed ) {
            // Shortcuts
            if ( (match = rquickExpr.exec( selector )) ) {//先看是不是简单的ID选择器 TAG选择器 类选择器
                // Speed-up: Sizzle("#ID")
                if ( (m = match[1]) ) {
                    if ( nodeType === 9 ) {
                        elem = context.getElementById( m );
                        // Check parentNode to catch when Blackberry 4.6 returns
                        // nodes that are no longer in the document #6963
                        if ( elem && elem.parentNode ) {
                            // Handle the case where IE, Opera, and Webkit return items
                            // by name instead of ID
                            if ( elem.id === m ) {
                                results.push( elem );
                                return results;
                            }
                        } else {
                            return results;
                        }
                    } else {
                        // Context is not a document
                        if ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) &&
                            contains( context, elem ) && elem.id === m ) {
                            results.push( elem );
                            return results;
                        }
                    }
    
                // Speed-up: Sizzle("TAG")
                } else if ( match[2] ) {
                    push.apply( results, context.getElementsByTagName( selector ) );
                    return results;
    
                // Speed-up: Sizzle(".CLASS")
                } else if ( (m = match[3]) && support.getElementsByClassName && context.getElementsByClassName ) {
                    push.apply( results, context.getElementsByClassName( m ) );
                    return results;
                }
            }
    
            // QSA path 是否支持document.querySelectorAll
            if ( support.qsa && (!rbuggyQSA || !rbuggyQSA.test( selector )) ) {
                nid = old = expando;
                newContext = context;
                newSelector = nodeType === 9 && selector;
    
                // qSA works strangely on Element-rooted queries
                // We can work around this by specifying an extra ID on the root
                // and working up from there (Thanks to Andrew Dupont for the technique)
                // IE 8 doesn't work on object elements
                if ( nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) {
                    groups = tokenize( selector );
    
                    if ( (old = context.getAttribute("id")) ) {
                        nid = old.replace( rescape, "\$&" );
                    } else {
                        context.setAttribute( "id", nid );
                    }
                    nid = "[id='" + nid + "'] ";
    
                    i = groups.length;
                    while ( i-- ) {
                        groups[i] = nid + toSelector( groups[i] );
                    }
                    newContext = rsibling.test( selector ) && context.parentNode || context;
                    newSelector = groups.join(",");
                }
    
                if ( newSelector ) {
                    try {
                        push.apply( results,
                            newContext.querySelectorAll( newSelector )
                        );
                        return results;
                    } catch(qsaError) {
                    } finally {
                        if ( !old ) {
                            context.removeAttribute("id");
                        }
                    }
                }
            }
        }
    
        // All others
        //去除选择器首位空格,并进入select函数
        return select( selector.replace( rtrim, "$1" ), context, results, seed );
    }

    先看:rquickExpr

    rquickExpr = /^(?:#([w-]+)|(w+)|.([w-]+))$/,
    当执行:match = rquickExpr.exec( selector ),产生一个长度为4的数组:其中match[1]ID匹配项,match[2]为tag匹配项,match[3]为类匹配项
    比如:当执行$("div")时,
    match=["div", undefined, "div", undefined]
    接下来就判断具体符合哪种选择器了,然后用原生方法直接获得。

    如果不是上述三种选择器,那么开始试探querySelectorAll:
    // QSA path 是否支持document.querySelectorAll
            if ( support.qsa && (!rbuggyQSA || !rbuggyQSA.test( selector )) ) {

    然后就就开始try尝试:

    if ( newSelector ) {
                    try {
                        push.apply( results,
                            newContext.querySelectorAll( newSelector )
                        );
                        return results;
                    } catch(qsaError) {
                    } finally {
                        if ( !old ) {
                            context.removeAttribute("id");
                        }
                    }
                }

    如果成功就返回results

  • 相关阅读:
    [时间篇TIME]Learn with whole Life 一生的学习
    使用IIS内置压缩功能,增加网站访问速度
    CSS中A链接样式的 "爱恨"原则
    爱情六十三课,定个开放日
    给爱子的信
    在IE中使用高级CSS3选择器
    爱情六十七课,下台阶的学问
    网上常用免费WebServices集合
    美国狗证上的10句话
    爱情六十五课,情爱无智者
  • 原文地址:https://www.cnblogs.com/mufc-go/p/3301269.html
Copyright © 2020-2023  润新知