麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

首頁(yè) > 學(xué)院 > 開發(fā)設(shè)計(jì) > 正文

如何理解與簡(jiǎn)化jquery的closest函數(shù)

2019-11-17 03:35:19
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

在實(shí)現(xiàn)delegate方法中,有一個(gè)很重要的輔助函數(shù)叫closest,雖然現(xiàn)在它歸類為遍歷節(jié)點(diǎn)這個(gè)模塊中。這個(gè)函數(shù)實(shí)現(xiàn)得非常復(fù)雜,洋洋灑灑近50行,完全不符合極限編程的規(guī)矩。

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 ];//這里頻繁創(chuàng)建新的jQuery對(duì)象與使用is這樣復(fù)雜的方法,我不覺得其高效到哪里去 

 

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

},

恰逢我也想造個(gè)輪子,便去研究它一翻,發(fā)現(xiàn)其第一個(gè)可以是字符串,元素節(jié)點(diǎn)或jQuery對(duì)象,還有一個(gè)可選參數(shù),上下文。看源碼前幾句,發(fā)現(xiàn)有個(gè)分支是判斷是否是Array,估計(jì)是供內(nèi)部調(diào)用的優(yōu)化代碼,可以無(wú)視之。于是其方法簡(jiǎn)化為:

closest: function( selectors, context ) { 

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

     

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

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

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

        0; 

    //遍歷原jQuery對(duì)象的節(jié)點(diǎn) 

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

        cur = this[i]; 

  

        while ( cur ) { 

            //如果是jQuery對(duì)象,則判定其是否包含當(dāng)前節(jié)點(diǎn),否則使用matchesSelector方法判定這個(gè)節(jié)點(diǎn)是否匹配給定的表達(dá)式selectors 

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

                //是則放入選擇器中 

                ret.push( cur ); 

                break; 

  

            } else { 

                //  否則把當(dāng)前節(jié)點(diǎn)變?yōu)槠涓腹?jié)點(diǎn) 

                cur = cur.parentNode; 

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

                    break; 

                } 

            } 

        } 

    } 

    //如果大于1,進(jìn)行唯一化操作 

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

    //將節(jié)點(diǎn)集合重新包裝成一個(gè)新jQuery對(duì)象返回 

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

},

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

closest: function( selectors ) { 

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

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

    var node =  selectors.nodeType ? selectors :false; 

    var nodes = [].slice.call(this);//將jQuery對(duì)象轉(zhuǎn)換為純數(shù)組 

    //遍歷原jQuery對(duì)象的節(jié)點(diǎn) 

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

        cur = this[i]; 

  

        while ( cur ) { 

            //如果是jQuery對(duì)象,則判定其是否包含當(dāng)前節(jié)點(diǎn),否則使用matchesSelector方法判定這個(gè)節(jié)點(diǎn)是否匹配給定的表達(dá)式selectors 

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

                //indexOf方法在某些瀏覽器需要自行實(shí)現(xiàn) 

                //是則放入選擇器中 

                ret.push( cur ); 

                break; 

            } else { 

                //  否則把當(dāng)前節(jié)點(diǎn)變?yōu)槠涓腹?jié)點(diǎn) 

                cur = cur.parentNode; 

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

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

                    break; 

                } 

            } 

        } 

    } 

    //如果大于1,進(jìn)行唯一化操作 

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

    //將節(jié)點(diǎn)集合重新包裝成一個(gè)新jQuery對(duì)象返回 

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

},

注意,jquery1.6中closest方法不再是返回包含一個(gè)或零個(gè)節(jié)點(diǎn)的jQuery對(duì)象了,再是對(duì)應(yīng)多個(gè)了(因此jQuery官網(wǎng)文檔是錯(cuò)誤的,沒有即時(shí)同步這變化.)

<!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>

下面是我的實(shí)現(xiàn):

closest: function( exPR ) { 

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

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

    //遍歷原dom對(duì)象的節(jié)點(diǎn) 

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

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

            //如果是dom對(duì)象,則判定其是否包含當(dāng)前節(jié)點(diǎn),否則使用matchesSelector方法判定這個(gè)節(jié)點(diǎn)是否匹配給定的表達(dá)式expr 

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

                //indexOf方法在某些瀏覽器需要自行實(shí)現(xiàn) 

                //是則放入選擇器中 

                ret.push( cur ); 

                break; 

            } else { 

                // 否則把當(dāng)前節(jié)點(diǎn)變?yōu)槠涓腹?jié)點(diǎn) 

                cur = cur.parentNode; 

            } 

        } 

    } 

    //如果大于1,進(jìn)行唯一化操作 

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

    //將節(jié)點(diǎn)集合重新包裝成一個(gè)新dom對(duì)象返回 

    return this.labor(ret); 

},


發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 未成年人在线观看 | 欧美一a一片一级一片 | 欧美日韩在线视频观看 | 国产免费激情视频 | 黑人操穴| 色视频91 | 4p嗯啊巨肉寝室调教男男视频 | 最新av免费网址 | 91社区电影 | 国产免费传媒av片在线 | 亚洲小视频在线 | 久在线观看福利视频69 | 91成人免费在线观看 | 久久超| 羞羞视频.www在线观看 | 日本一区二区在线 | 成人宗合网 | 久久艹综合 | 成年人免费高清视频 | 99ri精品 | 久久影院一区二区三区 | a免费看 | 欧美日韩亚洲一区二区三区 | 欧美性生活免费视频 | 色999中文字幕 | 黄色网址你懂的 | 日本a在线观看 | 国产高清成人久久 | 欧美人成在线 | 免费a级片在线观看 | 国产免费久久久久 | 美女久久久久久久久 | 久久久精品视频免费看 | 久久久久久久久久久影视 | 日韩精品久久久久久久电影99爱 | 玖草| 亚洲午夜天堂吃瓜在线 | 黄色一级片免费在线观看 | 久久男 | 国产日韩中文字幕 | 7777视频|