jquery3.0源码解读(三)Selector

前置知识

  • 正则表达式
  • css选择器
  • DOM
  • call

代码概况

第一节将jQuery初始化的时候,我们只是简单讲了下jQuery的构造方式,并没有分析jQuery对象到底是如何具体构造出来的。

使用过jquery的同学一定知道,jquery的一个最大的用的最多的特性就是用来选择页面上的元素,这个真是太方便,太强大了。换句话说,构造jquery对象的过程,就是选择器的实现过程。下面,我们来分析选择器的实现(其实是jquery对象的构造过程)。

打开/src/selector.js,代码如下:

define( [ "./selector-sizzle" ], function() {} );

直接指向selector-sizzle,那我们接着打开/src/selector-sizzle.js,代码如下:

define( [
    "./core",
    "../external/sizzle/dist/sizzle"
], function( jQuery, Sizzle ) {

"use strict";

jQuery.find = Sizzle;
jQuery.expr = Sizzle.selectors;

// Deprecated
jQuery.expr[ ":" ] = jQuery.expr.pseudos;
jQuery.uniqueSort = jQuery.unique = Sizzle.uniqueSort;
jQuery.text = Sizzle.getText;
jQuery.isXMLDoc = Sizzle.isXML;
jQuery.contains = Sizzle.contains;
jQuery.escapeSelector = Sizzle.escape;

} );

注意到jQuery.find = Sizzle;,这个Sizzle本身就是一个纯javascript实现的css选择器引擎。换句话说,就是css选择器的功能,用js也能做到。光是用这个,就完成了jquery选择器的大部分功能。

jQuery的find功能我们也经常使用,这里其实就是直接使用了Sizzle引擎。

功能说明

jquery的选择器大概有如下几种功能用法(这里又是大量的重载):

  1. jQuery(selector[,context])
    在context(作为待查找的 DOM 元素集、文档或 jQuery 对象)中通过selector(用来查找的字符串)查找所有匹配的元素

  2. jQuery(element)
    把element(DOM元素)封装成jQuery对象

  3. jQuery(elementArray)
    把elementArray(DOM元素数组)封装成jQuery对象

  4. jQuery(Object)
    把Object(任意对象)封装成jQuery对象

  5. jQuery(jQueryObject)
    相当于克隆了一个jQueryObject对象

  6. jQuery(html[,owerDocument])
    使用html字符串(用于动态创建DOM元素的HTML标记字符串),在owerDocument(创建DOM元素所在的文档)动态创建由jQuery对象包装的DOM元素

  7. jQuery()
    创建空jquery对象

  8. jQuery(html,attributes)
    使用html字符串(用于动态创建DOM元素的HTML标记字符串)动态创建由jQuery对象包装的DOM元素,并设置attributes(用于附加到新创建元素上的属性、事件和方法)

  9. jQuery(callback)
    允许你绑定一个在DOM文档载入完成后执行的函数,$(document).ready()的简写。

源码分析

源码如下:

init = jQuery.fn.init = function( selector, context, root ) {
        var match, elem;

        if ( !selector ) {
            return this;
        }

        root = root || rootjQuery;

        if ( typeof selector === "string" ) {
            if ( selector[ 0 ] === "<" &&
                selector[ selector.length - 1 ] === ">" &&
                selector.length >= 3 ) {

                match = [ null, selector, null ];

            } else {
                match = rquickExpr.exec( selector );
            }

            if ( match && ( match[ 1 ] || !context ) ) {

                if ( match[ 1 ] ) {
                    context = context instanceof jQuery ? context[ 0 ] : context;

                    jQuery.merge( this, jQuery.parseHTML(
                        match[ 1 ],
                        context && context.nodeType ? context.ownerDocument || context : document,
                        true
                    ) );

                    if ( rsingleTag.test( match[ 1 ] ) && jQuery.isPlainObject( context ) ) {
                        for ( match in context ) {

                            if ( jQuery.isFunction( this[ match ] ) ) {
                                this[ match ]( context[ match ] );

                            } else {
                                this.attr( match, context[ match ] );
                            }
                        }
                    }

                    return this;

                } else {
                    elem = document.getElementById( match[ 2 ] );

                    if ( elem ) {

                        this[ 0 ] = elem;
                        this.length = 1;
                    }
                    return this;
                }

            } else if ( !context || context.jquery ) {
                return ( context || root ).find( selector );

            } else {
                return this.constructor( context ).find( selector );
            }

        } else if ( selector.nodeType ) {
            this[ 0 ] = selector;
            this.length = 1;
            return this;

        } else if ( jQuery.isFunction( selector ) ) {
            return root.ready !== undefined ?
                root.ready( selector ) :

                selector( jQuery );
        }

        return jQuery.makeArray( selector, this );
    };

第一步:判断selector是否为空,是的话,直接返回this,也就是空的jquery对象。用法7解决;

第二步:定义了root为rootjQuery,这里的rootjQuery其实就是jQuery( document ),主要用于选择器为空的时候,用rootjQuery上下文来代替空值,继续下面的链式操作(关于链式操作,我们在下一节中讲);

第三步:判断selector是否为字符串、是否为DOM类型、是否是一个function。字符串先保留;如果是DOM类型的话,this[ 0 ] = selector;长度赋值1,用法2解决;如果是function的话,判断document是否ready,如果ready,就执行function,用法9解决(关于ready的实现,见之前的文章);

第四步:如果selector为字符串,通过正则判断selector是不是html字符串,如果不是,判断有没有context,有的话,使用context调用find方法(也就是sizzle),没有就是用document为context调用find。用法1解决;

第五步:如果selector为html字符串,这里说明一下rquickExpr,这个是用来匹配HTML标记和ID表达式,匹配后的结果,也就是match,为[找到的匹配,HTML标记,ID]。判断match[1]也就是HTML标记是否存在,如果不存在,直接通过match[ 2 ]也就是ID去取对应元素;

第六步:如果match[1]存在,jquery通过parseHTML(将html字符串转换为dom)和merge(把第二个数组merge到第一个数组)方法,将HTML标记转化为由jQuery对象包装的DOM元素,并返回,用法6解决;如果有attributes的话,添加属性,用法8解决;

第七步:剩下的还有用法3,4,5,它们都会被jQuery.makeArray处理。大致的意思就是处理成jquery数组,这里的makeArray对外是将一个类数组对象转换为真正的数组对象,对内有个重载,就是处理成jquery数组对象。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值