您的位置:首页 > Web前端 > JQuery

jquery3.0源码解读(三)Selector

2016-09-12 15:17 316 查看

前置知识

正则表达式

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的选择器大概有如下几种功能用法(这里又是大量的重载):

jQuery(selector[,context])

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

jQuery(element)

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

jQuery(elementArray)

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

jQuery(Object)

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

jQuery(jQueryObject)

相当于克隆了一个jQueryObject对象

jQuery(html[,owerDocument])

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

jQuery()

创建空jquery对象

jQuery(html,attributes)

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

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数组对象。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息