jquery3.0源码解读(三)Selector

来源:互联网 发布:社交媒体网络安全问题 编辑:程序博客网 时间:2024/06/05 07:38

前置知识

  • 正则表达式
  • 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;// DeprecatedjQuery.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数组对象。

0 0