美文网首页
jquery index()方法源码解析

jquery index()方法源码解析

作者: kofzx | 来源:发表于2019-04-11 23:08 被阅读0次

平时工作中,相信很多小伙伴跟我一样,jquery的index()方法用的很多,也用得很爽,一直都觉得不可思议。今天就偶然想了解一下它的实现原理,便翻起了jquery的源码,窥得了它大致的实现原理。

场景重现:(jquery自行引入)

html:

<ul id="test">
    <li id="t1">1</li>
    <li id="t2">2</li>
    <li id="t3">3</li>
</ul>

js:

$("#test").on('click', 'li', function(e) {
    console.log($(this).index());
})

就如此小的一个demo,引发了我对index()方法的种种联想,为什么点击当前的元素可以知道它的索引呢?难道要预先知道它的父级吗,这不可能,这些dom节点又不是固定的,那到底。。。。。。

下面就开启源码之旅吧。

首先是index()方法,其源码如下:

index: function( elem ) {
    // No argument, return index in parent
    if ( !elem ) {
        return ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1;
    }
    // Index in selector
    if ( typeof elem === "string" ) {
        return indexOf.call( jQuery( elem ), this[ 0 ] );
    }
    // Locate the position of the desired element
    return indexOf.call( this,
        // If it receives a jQuery object, the first element is used
        elem.jquery ? elem[ 0 ] : elem
    );
}

源码很精简,而且我们只想看没传参时的index方法的用法,所以只看这句:

if ( !elem ) {
    return ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1;
}

其实这句的重点在prevAll方法,其它都是些使逻辑严谨的代码,因此我们侧重点放在prevAll方法。所以,翻看了prevAll方法:

jQuery.each({
    // ...此处省略了很多非相关代码
    prevAll: function( elem ) {
      return dir( elem, "previousSibling" );
    },
}, function(name, fn) { // ...省略 })

紧接着,我们看dir源码:

function dir( elem, dir, until ) {
    var matched = [],
        truncate = until !== undefined;

    while ( ( elem = elem[ dir ] ) && elem.nodeType !== 9 ) {
        if ( elem.nodeType === 1 ) {
            if ( truncate && jQuery( elem ).is( until ) ) {
                break;
            }
            matched.push( elem );
        }
    }
    return matched;
}

看到这里,其实大致思路已经知道了:遍历查找当前元素的上一个同级元素,形成一个包含所有该元素的前面的元素的集合。可能有点拗口,回到我们的小demo,在控制台模拟一下prevAll的过程,看着以下截图应该好理解些:


控制台模拟

而dir函数已经为我们过滤了文本节点:

if ( elem.nodeType === 1 )

最终就是返回一个所有的前面元素的集合给我们了,然后index就是prevAll().length(该集合的长度)了。

ps: 可能细心的小伙伴会发现有漏洞,index源码上是这样的:

if ( !elem ) {
    return ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1;
}

人家的prevAll明明没传参数,那按道理prevAll就接收不到elem参数,则elem为undefined,那就没有后续的故事情节了。关于这个,我只想说,你知道得太多了。。。。。。


xx

由于本人精力有限,所以只能猜想是jQuery.each方法做了手脚,使得不传参的prevAll里面的elem自动变为this对象。(当然这只是本人猜想),希望有知道的留言一下,共勉,谢谢大家。

相关文章

网友评论

      本文标题:jquery index()方法源码解析

      本文链接:https://www.haomeiwen.com/subject/typfwqtx.html