亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

如何理解與簡化jquery的closest函數

2019-11-17 03:35:19
字體:
來源:轉載
供稿:網友

在實現delegate方法中,有一個很重要的輔助函數叫closest,雖然現在它歸類為遍歷節點這個模塊中。這個函數實現得非常復雜,洋洋灑灑近50行,完全不符合極限編程的規矩。

closest: function( selectors, context ) { 

    var ret = [], i, l, cur = this[0]; 

      

    // Array 

    if ( jQuery.isArray( selectors ) ) {//這分支的過濾邏輯基本與下面的一致 

        var match, selector, 

            matches = {}, 

            level = 1; 

 

        if ( cur && selectors.length ) { 

            for ( i = 0, l = selectors.length; i < l; i++ ) { 

                selector = selectors[i]; 

 

                if ( !matches[ selector ] ) { 

                    matches[ selector ] = POS.test( selector ) ? 

                        jQuery( selector, context || this.context ) : 

                        selector; 

                } 

            } 

 

            while ( cur && cur.ownerDocument && cur !== context ) { 

                for ( selector in matches ) { 

                    match = matches[ selector ];//這里頻繁創建新的jQuery對象與使用is這樣復雜的方法,我不覺得其高效到哪里去 

 

                    if ( match.jquery ? match.index( cur ) > -1 : jQuery( cur ).is( match ) ) { 

                        ret.push({ selector: selector, elem: cur, level: level }); 

                    } 

                } 

 

                cur = cur.parentNode; 

                level++; 

            } 

        } 

 

        return ret; 

    } 

 

    // String 

    var pos = POS.test( selectors ) || typeof selectors !== "string" ? 

            jQuery( selectors, context || this.context ) : 

            0; 

 

    for ( i = 0, l = this.length; i < l; i++ ) { 

        cur = this[i]; 

 

        while ( cur ) { 

            if ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) { 

                ret.push( cur ); 

                break; 

 

            } else { 

                cur = cur.parentNode; 

                if ( !cur || !cur.ownerDocument || cur === context || cur.nodeType === 11 ) { 

                    break; 

                } 

            } 

        } 

    } 

 

    ret = ret.length > 1 ? jQuery.unique( ret ) : ret; 

 

    return this.pushStack( ret, "closest", selectors ); 

},

恰逢我也想造個輪子,便去研究它一翻,發現其第一個可以是字符串,元素節點或jQuery對象,還有一個可選參數,上下文???a >源碼前幾句,發現有個分支是判斷是否是Array,估計是供內部調用的優化代碼,可以無視之。于是其方法簡化為:

closest: function( selectors, context ) { 

    var ret = [], i, l, cur = this[0]; 

     

    // 如果字符串包含位置偽類或者是個元素節點,則封裝為一個jQuery對象,否則為0(即false的簡寫,用于快速跳過分支) 

    var pos = POS.test( selectors ) || typeof selectors !== "string" ? 

        jQuery( selectors, context || this.context ) : 

        0; 

    //遍歷原jQuery對象的節點 

    for ( i = 0, l = this.length; i < l; i++ ) { 

        cur = this[i]; 

  

        while ( cur ) { 

            //如果是jQuery對象,則判定其是否包含當前節點,否則使用matchesSelector方法判定這個節點是否匹配給定的表達式selectors 

            if ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) { 

                //是則放入選擇器中 

                ret.push( cur ); 

                break; 

  

            } else { 

                //  否則把當前節點變為其父節點 

                cur = cur.parentNode; 

                if ( !cur || !cur.ownerDocument || cur === context || cur.nodeType === 11 ) { 

                    break; 

                } 

            } 

        } 

    } 

    //如果大于1,進行唯一化操作 

    ret = ret.length > 1 ? jQuery.unique( ret ) : ret; 

    //將節點集合重新包裝成一個新jQuery對象返回 

    return this.pushStack( ret, "closest", selectors ); 

},

由于本人很反感位置偽類,認為其違反選擇器的法則之一(由關系選擇器隔開的各選擇器分組內部,它們的位置是隨意的),因此有關位置偽類的邏輯我也去掉了。

closest: function( selectors ) { 

    var ret = [], i, l, cur = this[0]; 

    // 如果字符串包含位置偽類或者是個元素節點,則封裝為一個jQuery對象,否則為0(即false的簡寫,用于快速跳過分支) 

    var node =  selectors.nodeType ? selectors :false; 

    var nodes = [].slice.call(this);//將jQuery對象轉換為純數組 

    //遍歷原jQuery對象的節點 

    for ( i = 0, l = this.length; i < l; i++ ) { 

        cur = this[i]; 

  

        while ( cur ) { 

            //如果是jQuery對象,則判定其是否包含當前節點,否則使用matchesSelector方法判定這個節點是否匹配給定的表達式selectors 

            if ( obj ? nodes.indexOf(node) > -1 : jQuery.find.matchesSelector(cur, selectors) ) { 

                //indexOf方法在某些瀏覽器需要自行實現 

                //是則放入選擇器中 

                ret.push( cur ); 

                break; 

            } else { 

                //  否則把當前節點變為其父節點 

                cur = cur.parentNode; 

                //如果沒有父節點(說明其還沒有插入DOM樹),或不是元素節點,或是文檔碎片(說明其剛被移出DOM樹) 

                if ( !cur || !cur.ownerDocument || cur.nodeType === 11 ) { 

                    break; 

                } 

            } 

        } 

    } 

    //如果大于1,進行唯一化操作 

    ret = ret.length > 1 ? jQuery.unique( ret ) : ret; 

    //將節點集合重新包裝成一個新jQuery對象返回 

    return $(ret);//本人覺得pushStack真是個邪惡的方法,讓菜鳥不籽有鏈下去的欲望,殊不知這是維護的大敵 

},

注意,jquery1.6中closest方法不再是返回包含一個或零個節點的jQuery對象了,再是對應多個了(因此jQuery官網文檔是錯誤的,沒有即時同步這變化.)

<!doctype html> 

<html> 

  <head> 

    <title>closest在jquery1.6的改變 by 司徒正美</title> 

    <script src="jquery.js"></script> 

    <script> 

      $(function(){ 

        $("p").delegate("strong","click",function(){ 

          alert(this.innerHTML) 

        }); 

        alert($("strong").closest("p").length) 

      }); 

  

    </script> 

  

  </head> 

  <body> 

    <p> 

      <strong>使用事件代理1</strong> 

    </p> 

    <p> 

      <strong>使用事件代理2</strong> 

    </p> 

    <p> 

      <strong>使用事件代理3</strong> 

    </p> 

  </body> 

</html>

下面是我的實現:

closest: function( exPR ) { 

    // 如果字符串包含位置偽類或者是個元素節點,則封裝為一個dom對象,否則為0(即false的簡寫,用于快速跳過分支) 

    var node =  expr.nodeType ? expr : 0, nodes = dom.slice(this);//將它轉換為純數組 

    //遍歷原dom對象的節點 

    for (var i = 0, ret = [], cur; cur = this[i++];) {//由于肯定里面都是節點,因此可以使用這種循環 

        while (cur && cur.nodeType === 1 ) { 

            //如果是dom對象,則判定其是否包含當前節點,否則使用matchesSelector方法判定這個節點是否匹配給定的表達式expr 

            if ( node ? nodes.indexOf(node) > -1 : matchElement( cur, expr ) ){ 

                //indexOf方法在某些瀏覽器需要自行實現 

                //是則放入選擇器中 

                ret.push( cur ); 

                break; 

            } else { 

                // 否則把當前節點變為其父節點 

                cur = cur.parentNode; 

            } 

        } 

    } 

    //如果大于1,進行唯一化操作 

    ret = ret.length > 1 ? dom.unique( ret ) : ret; 

    //將節點集合重新包裝成一個新dom對象返回 

    return this.labor(ret); 

},


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
久久免费少妇高潮久久精品99| 久久天天躁狠狠躁夜夜躁| 日韩免费在线电影| 国产精品久久久久久久久久| 热99精品只有里视频精品| 久久精品久久久久久国产 免费| 日韩最新中文字幕电影免费看| 精品国产成人av| 欧美黑人一区二区三区| 亚洲大胆美女视频| 欧美午夜片欧美片在线观看| 久久成人精品电影| 色噜噜狠狠色综合网图区| 欧美日韩日本国产| 欧美人交a欧美精品| 久久久噜噜噜久久中文字免| 国产一区二区三区久久精品| 川上优av一区二区线观看| 欧美午夜精品久久久久久人妖| 久久91亚洲精品中文字幕奶水| 国产欧美一区二区三区久久人妖| 欧美在线观看视频| 欧美午夜精品久久久久久人妖| 亚洲无限乱码一二三四麻| 成人激情在线观看| 日韩精品免费在线观看| 美日韩丰满少妇在线观看| 成人在线播放av| 在线观看欧美成人| 欧美壮男野外gaytube| 日产日韩在线亚洲欧美| 国产精品欧美激情在线播放| 欧美视频在线观看 亚洲欧| 日韩欧美视频一区二区三区| 国产精品久久久久久久久久久久久| 亚洲成人网在线观看| 亚洲精品动漫久久久久| 国产精品一区二区女厕厕| 亚洲天堂2020| 欧美亚洲一级片| 国产欧美va欧美va香蕉在| 亚洲国产高清自拍| 欧美日韩亚洲系列| 亚洲精品91美女久久久久久久| 亚洲性猛交xxxxwww| 麻豆成人在线看| 4438全国成人免费| 久久精品亚洲国产| 国产精品激情av在线播放| 日韩av最新在线观看| 97视频免费在线观看| 精品久久香蕉国产线看观看亚洲| 神马国产精品影院av| 成人国产精品久久久| 亚洲天堂网站在线观看视频| 最近中文字幕日韩精品| 68精品国产免费久久久久久婷婷| 亚洲成人黄色网| 在线视频免费一区二区| 久久激情视频免费观看| 国产精品极品在线| 色偷偷av一区二区三区| 亚洲欧美日韩综合| 亚洲福利视频二区| 97精品久久久中文字幕免费| 日韩一二三在线视频播| 亚洲最大成人免费视频| 欧美日韩免费在线| 日韩视频免费观看| 国产精品嫩草影院一区二区| 精品一区二区三区三区| 日韩在线观看免费高清| 精品成人国产在线观看男人呻吟| 亚洲香蕉成人av网站在线观看| 欧美性极品少妇精品网站| 国产精品99久久99久久久二8| 日韩av在线免费看| 欧美极度另类性三渗透| 日韩在线免费观看视频| 久久久视频在线| 亚洲成人精品久久久| 中文字幕9999| 2019中文在线观看| 91久久久久久久一区二区| 欧美激情视频一区| 亚洲欧洲日产国码av系列天堂| 亚洲影院污污.| 欧美高清videos高潮hd| 视频在线一区二区| 97精品国产97久久久久久免费| 国产精品视频免费观看www| 亚洲男女自偷自拍图片另类| 久久视频这里只有精品| 国产精品久久久久久久9999| 日韩中文字幕国产| 国产精品pans私拍| 日韩在线视频中文字幕| 国产精欧美一区二区三区| 国产精品久久久久久中文字| 国产一区二区三区视频在线观看| 色偷偷噜噜噜亚洲男人的天堂| 精品国产一区二区三区久久狼5月| 久久久久久久久久久久久久久久久久av| 亚洲欧洲第一视频| 国产精品91一区| 亚洲第一福利网| 国产精品成久久久久三级| 欧美日韩第一视频| 欧美成人四级hd版| 91久久国产婷婷一区二区| 国产精品日日摸夜夜添夜夜av| 国语对白做受69| 日产精品久久久一区二区福利| 亚洲91精品在线观看| 欧美精品在线观看| 国产精品扒开腿做爽爽爽的视频| 亚洲乱码一区av黑人高潮| 日韩av影院在线观看| 免费97视频在线精品国自产拍| 亚洲天堂av在线免费| 91在线视频成人| 亚洲小视频在线| 色悠悠国产精品| 日韩有码在线电影| 日韩欧美福利视频| 高清亚洲成在人网站天堂| 亚洲成色www8888| 亚洲国语精品自产拍在线观看| 亚洲精品按摩视频| 中文字幕免费精品一区高清| 亚洲精品成人久久| 91色精品视频在线| 欧美国产日韩一区二区三区| 午夜精品一区二区三区在线播放| 亚洲欧美中文字幕| 97在线看免费观看视频在线观看| 国产亚洲欧洲高清一区| 91网站免费观看| 午夜精品一区二区三区视频免费看| 91精品国产91久久久久福利| 日本精品中文字幕| 亚洲人成免费电影| 欧美午夜激情小视频| 欧美日韩免费看| 欧美中文在线观看国产| 91禁外国网站| 伊人一区二区三区久久精品| 91情侣偷在线精品国产| 亚洲最大中文字幕| 色婷婷亚洲mv天堂mv在影片| 国产v综合v亚洲欧美久久| 久久精品国产亚洲一区二区| 97在线视频免费| 国产精品美女主播在线观看纯欲| 国产精品一久久香蕉国产线看观看| 日韩欧美在线看| 亚洲国内高清视频| 久久国产精品亚洲| 国产精品色视频| 91在线无精精品一区二区| 91成人精品网站| 午夜精品久久久久久久99热| 亚洲第一中文字幕在线观看| 51色欧美片视频在线观看|