jQuery源码学习(2):选择器初窥
2016-03-29 22:34
381 查看
选择器初窥
代码架构:
jQuery选择器可以依照传入数据的类型分为五大类:传入字符串:$("div"), $("#id"), $(".div1"),$(".div p.title")
传入html代码:$("<div></div>"), $("<div>1</div><div>2</div>")
传入对象:$(document), $(this)
传入数组或对象字面量:$({}), $([])
传入函数:$(function(){})
下面我们来看一下jQuery构造函数代码(jQuery-2.2.2第2832行起)的架构:
jQuery.fn.init = function(selector, context){ if(!selector){ // part1.处理$(null), $(undefined), $(false), $("") } if(typeof selector == "string"){ // part2.匹配selector并将结果传入match中 } if(match && (match[1] || !context)){ // part3.创建标签或按#id查询 }else{ // part4.处理复杂选择器 } } // 一些其他的不常见情况 else {...} return jQuery.makeArray(selector, this); }
可以发现jQ将代码依照selector的类型分为了几个部分。下面我们来依次分析这几部分的代码。
第一部分:检测没有传入值的情况
此段完整代码如下:// HANDLE: $(""), $(null), $(undefined), $(false) if ( !selector ) { return this; }
第二部分:匹配传入的字符串
此段完整代码如下:if ( selector[ 0 ] === "<" &&selector[ selector.length - 1 ] === ">" &&selector.length >= 3 ) { // Assume that strings that start and end with <> are HTML and skip the regex check match = [ null, selector, null ]; } else { match = rquickExpr.exec( selector ); }
// 匹配html标签或#id rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,
通过分析rquickExpr正则表达式,我们可以得出在selector分别为以下几种值时返回值match的结构:
1. selector = "<div>"
match = [null, "<div>", null]
2. selector = "<div>content</div>"
match = [null, "<div>content</div>", null]
3. selector = "<div></div>content"
match = ["<div></div>content", "<div></div>", null]
4. selector = #id
match = [#id, null, #id]
第三部分:创建标签或者按#id查询
传入标签时:
此段完整代码如下:// 如果是html标签 if ( match[ 1 ] ) { // 如果传入的context是jQ对象,将其转换成原生对象 context = context instanceof jQuery ? context[0] : context; // 将传入的html字符串转换成节点数组并传入this中 jQuery.merge(this, jQuery.parseHTML(match[1], context && context.nodeType ? context.ownerDocument || context : document, true)); // 如果是$(html, props)的形式,则要设置对应属性或执行方法 if (rsingleTag.test(match[1]) && jQuery.isPlainObject(context)) { for (match in context) { // 若 prop 的某一项是jQ方法 if (jQuery.isFunction(this[match])) { this[match](context[match]); // 否则设置对应属性 } else { this.attr(match, context[match]); } } } return this; }
// 匹配单标签 var rsingleTag = ( /^<([\w-]+)\s*\/?>(?:<\/\1>|)$/ );
关键位置的语意都已在注释中讲解过了,下面主要介绍一下$.parseHTML和$.merge这两个方法在其中的应用:
jQuery.parseHTML( data [, context ] [, keepScripts ] )
data:需要被转换成节点的字符串
context:被转换的节点所存在的上下文。并没有太大用处,默认是document,在需要在iframe中进行操作时,也可以设成contentWindow。
keepScripts:布尔值。设置成true时允许将字符串中的<script>部分也转换成节点。
jQuery.merge(first, second)
我们经常用$.merge来进行数组的合并。在本例中需要强调的一点是,$.merge被用来将一个数组合并到类数组对象中。就像下面这样:
var obj = {0: "hello", 1: "pansy", length: 2}; var arr = ["from", "arr"]; console.log($.merge(obj, arr)); // Object {0: "hello", 1: "pansy", 2: "from", 3: "arr", length: 4}
传入id时:
// HANDLE: $(#id) else { elem = document.getElementById( match[ 2 ] ); // Support: Blackberry 4.6 // gEBID returns nodes no longer in the document (#6963) if ( elem && elem.parentNode ) { // Inject the element directly into the jQuery object this.length = 1; this[ 0 ] = elem; } this.context = document; this.selector = selector; return this; }
第四部分:处理复杂选择器
// 处理形如$(".class"), $("ul li+p")等等 if ( !context || context.jquery ) { return ( context || root ).find( selector ); // 当传入上下文是原生对象时,调用构造函数返回jQ对象 } else { return this.constructor( context ).find( selector ); }
此处复杂选择器全部借助$().find()方法实现,使用了sizzle引擎,我们稍后再进行介绍。
相关文章推荐
- jQuery源码学习(1):整体架构
- JQuery中click与live两种绑定click事件的区别
- vue和Jquery差别之动态添加删除元素
- 夜晚 暴力 十点钟 jQuery 的 extend 实现 原理
- jQuery 3 有哪些新东西
- jQuery源码浅析2–奇技淫巧
- 大白话讲解Promise(三)搞懂jquery中的Promise
- Ajax:后台jquery实现ajax无刷新删除数据及demo
- jquery学习
- jQuery的deferred对象详解
- Atitit。监听键盘上下左右方向键事件java js jquery c#.net
- Atitit。监听键盘上下左右方向键事件java js jquery c#.net
- Atitit。监听键盘上下左右方向键事件java js jquery c#.net
- jquery 和 原生js 获取<select><option></option></select>标签的值和文本
- 有关js、jquery操作table的例子
- 学习jquery的一些简单运用
- jquery.validation.js 表单验证 完整例子使用
- jQuery 效果 - 滑动
- jQueryEasyUI Messager基本使用
- JQuery AJAX