微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Jquery 1.9.1源码分析系列十二之筛选操作

废话不多说了直接奔入主题了。

rush:js;"> jQuery.fn.find( selector )

  find接受一个参数表达式selector:选择器(字符串)、DOM元素(Element)、jQuery对象。分两种情况处理:

  第一种,如果传入的参数是非字符串,则先通过jQuery选择器将selector查找出来,然后过滤出包含于当前jQuery对象所匹配的元素的节点。

rush:js;"> if ( typeof selector !== "string" ) { self = this; return this.pushStack( jQuery( selector ).filter(function() { for ( i = 0; i < len; i++ ) { if ( jQuery.contains( self[ i ],this ) ) { return true; } } }) ); }

可以看出过滤条件中jQuery.contains( self[ i ],this )是关键,该函数使用的是Sizzle选择器中的函数,在Sizzle引擎中有分析,详情点击。

第二种,如果选择器是字符串,调用jQuery.find (= Sizzle)直接处理

rush:js;"> ret = []; for ( i = 0; i < len; i++ ) { //第二个参数是表示context jQuery.find( selector,this[ i ],ret ); } //$( selector,context )变成$( context ).find( selector ),需要去重和pushStack ret = this.pushStack( len > 1 ? jQuery.unique( ret ) : ret ); ret.selector = ( this.selector ? this.selector + " " : "" ) + selector; return ret;
rush:js;"> jQuery.fn.closest( selectors,context )

  第二个参数是可选的。函数用于从当前匹配元素开始,逐级向上级选取符合指定表达式的第一个元素,并以jQuery对象的形式返回。

  这里的表达式包括:选择器(字符串)、DOM元素(Element)、jQuery对象。

  

代码中的处理步骤为

  1.根据传递的参数先查询出结果保存在pos中。

rush:js;"> pos = rneedsContext.test( selectors ) || typeof selectors !== "string" ? jQuery( selectors,context || this.context ) : 0;

  2.遍历当前jQuery对象的每一个元素,从这个元素开始,逐级向上级选取符合指定表达式的第一个祖先元素。

rush:js;"> for ( ; i < l; i++ ) { cur = this[i]; while ( cur && cur.ownerDocument && cur !== context && cur.nodeType !== 11 ) { if ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur,selectors) ) { ret.push( cur ); break; } cur = cur.parentNode; } } return this.pushStack( ret.length > 1 ? jQuery.unique( ret ) : ret );

  parents() 和 .closest() 方法类似,它们都沿 DOM 树向上遍历。但区别也很大closest找到第一个符合条件就截止,parents是找到所有符合条件的集合。

jQuery.fn. parent/ parents/ parentsUntil/ next/ prev/ nextAll/ prevAll/ nextUntil/ prevUntil/ siblings/ children/ contents详解

  

以上几组筛选被放在一起处理,源码如下

rush:js;"> jQuery.each({ parent: function( elem ) {…},parents: function( elem ) {…},parentsUntil: function( elem,i,until ) {…},next: function( elem ) {…},prev: function( elem ) {…},nextAll: function( elem ) {…},prevAll: function( elem ) {…},nextUntil: function( elem,prevUntil: function( elem,siblings: function( elem ) {…},children: function( elem ) {…},contents: function( elem ) {…} },function( name,fn ) { jQuery.fn[ name ] = function( until,selector ) { var ret = jQuery.map( this,fn,until ); //过滤 ... return this.pushStack( ret ); }; });

  可以看出,这几个筛选步骤一致。都是先通过map函数把当前jQuery对象每个匹配的元素代入相应的匹配函数(fn)中获取出结果然后在进行后续的过滤。

  我们先看一下后面的过滤(已经通过jQuery.map( this,until )获取到了备选种子ret)   首先,并不是所有的筛选函数都有until这个参数,只有以Until结尾的几个筛选才需要这个参数,其他的筛选只有selector这个参数。

rush:js;"> if ( !runtil.test( name ) ) { selector = until; }

  其次,如果有选择器,则通过选择器过滤一下先前查找结果ret

rush:js;"> if ( selector && typeof selector === "string" ) { ret = jQuery.filter( selector,ret ); }

  然后,guaranteedUnique里面的几种筛选条件(children/contents/next/prev)在当前jQuery对象所匹配的元素个数有多个的时候,通过每个匹配元素获取到的结果保存在结果集ret中,且不需要去重。其他筛选是要去重的。点击查看jQuery.unique方法详解

1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret;

  另外,还需要处理的特殊情况是: 如果当前jQuery对象所匹配的元素有多个,则使用parents /prevUntil /prevAll这三种筛选的结果需要倒序排列。需要倒序的原因:jQuery.unique使用的是Sizzle引擎中的排序函数Sizzle .uniqueSort,这个排序函数会根据文档最顶层对象到最底层的方式排列。

1 && rparentsprev.test( name ) ) { ret = ret.reverse(); }

  最后,返回包裹后的结果

rush:js;"> return this.pushStack( ret ); 

  上面说了主题的框架结构,下面说一下这一组筛选器匹配函数里面用到的两个函数jQuery.dir和jQuery. sibling,直接上源码 //从当前元素elem指定的dir对应的节点开始一直查找dir,并将这些节点保存在matched中,直到循环终止。注意:结果中不包含elem节点

rush:js;"> dir: function( elem,dir,until ) { var matched = [],cur = elem[ dir ]; while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) { if ( cur.nodeType === 1 ) { matched.push( cur ); } cur = cur[dir]; } return matched; },//获取节点n及其兄弟节点中非elem的节点集合r sibling: function( n,elem ) { var r = []; for ( ; n; n = n.nextSibling ) { if ( n.nodeType === 1 && n !== elem ) { r.push( n ); } } return r; } //找到当前元素cur的下一个dir为止 function sibling( cur,dir ) { do { cur = cur[ dir ]; } while ( cur && cur.nodeType !== 1 ); return cur; } 
rush:js;"> jQuery.fn.add( selector,context )和jQuery.fn. addBack( selector )

  add函数是向当前匹配元素中添加符合指定表达式的元素,并以jQuery对象的形式返回。add可以接收包括:选择器(字符串)、HTML内容(字符串)、DOM元素(Element)、jQuery对象。处理比较简单,直接上源码

rush:js;"> add: function( selector,context ) { var set = typeof selector === "string" ? jQuery( selector,context ) : jQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ),//把selector表达式获取的结果集拼接到当前对象上 all = jQuery.merge( this.get(),set ); //返回新的拼接结果 return this.pushStack( jQuery.unique(all) ); }   jQuery.fn.add和jQuery.fn.not相对应。jQuery.fn.not后面再说。   jQuery.fn.addBack将之前匹配的元素加入到当前匹配的元素中,并以新的jQuery对象的形式返回。 addBack: function( selector ) { return this.add( selector == null ? this.prevObject : this.prevObject.filter(selector) ); } jQuery.fn.andSelf = jQuery.fn.addBack;    jQuery.fn.not( selector )和jQuery.fn.filter( selector ) not: function( selector ) { return this.pushStack( winNow(this,selector,false) ); } filter: function( selector ) { return this.pushStack( winNow(this,true) ); },

  not和filter都是操作本身的集合,not是过滤掉本身集合中满足过滤条件selector的项,留下其他项。而filter是留下满足过滤条件selector的项。

  关键是function winNow( elements,qualifier,keep )函数。这个函数功能是执行相同的过滤或者不过滤的功能。过滤条件qualifier有三种:函数、DOM节点、字符串。keep:true表示保留满足过滤条件的项,false表示保留不满足过滤条件的项。

winNow的源码注释如下

= 0 ) === keep; }); }

  其中用到jQuery.grep,grep详解点击这里。

  jQuery.filter( expr,elems,not )这个低级api专门用来处理jQuery.fn.filter中过滤条件为字符串的情况。

rush:js;"> jQuery.filter: function( expr,not ) { if ( not ) { expr = ":not(" + expr + ")"; } //其中matchesSelector和matches是Sizzle中的函数。matchesSelector是判断单个元素elem是否满足表达式expr,matches是查找元素集合elems中满足表达式expr的项 return elems.length === 1 ? jQuery.find.matchesSelector(elems[0],expr) ? [ elems[0] ] : [] : jQuery.find.matches(expr,elems); },jQuery.fn.index( elem )

  index函数实际上是一个功能函数的集合。

  第一个功能:不传递elem参数,则表示取当前jQuery对象(jQuery对象的第一个元素)在其所有同辈元素中的位置。

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

  第二个功能:如果参数为String类型则将其视作选择器,返回当前元素在选择器所匹配的元素中的索引位置。如果该选择器不匹配任何元素或者当前元素不在匹配到的元素内,则返回-1。

rush:js;"> if ( typeof elem === "string" ) { //在数组jQuery( elem )中搜索指定的值,并返回其索引值 return jQuery.inArray( this[0],jQuery( elem ) ); }

  第三个功能:如果object为DOM元素或jQuery对象,则返回该元素(或该jQuery对象中的第一个元素)在当前jQuery对象所匹配的元素中的索引位置。

rush:js;"> return jQuery.inArray(elem.jquery ? elem[0] : elem,this ); 

  其他的筛选处理就不分析了。看源码即可明白。

jquery选择器

ottom: rgb(170,170,170) 1px solid; text-align: left; border-left: rgb(170,170) 1px solid; padding-bottom: 0px; widows: 1; text-transform: none; background-color: rgb(249,249,249); text-indent: 0px; margin: 10px 0px 0px; padding-left: 0px; width: 709px; letter-spacing: normal; padding-right: 0px; border-collapse: collapse; font: 12px Verdana,Arial,宋体; white-space: normal; color: rgb(0,0); border-top: rgb(170,170) 1px solid; border-right: rgb(170,170) 1px solid; word-spacing: 0px; padding-top: 0px; -webkit-text-stroke-width: 0px"> ottom: 0px; border-left: 0px; padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; border-top: 0px; border-right: 0px; padding-top: 0px"> ottom: 0px; border-left: 0px; padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; border-top: 0px; border-right: 0px; padding-top: 0px"> ottom: 0px; border-left: 0px; padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; border-top: 0px; border-right: 0px; padding-top: 0px">
ottom: rgb(170,170) 1px solid; padding-bottom: 5px; background-color: rgb(213,213,213); margin: 0px; padding-left: 6px; padding-right: 15px; vertical-align: baseline; border-top: rgb(170,170) 1px solid; padding-top: 5px">选择器 ottom: rgb(170,170) 1px solid; padding-top: 5px">实例 ottom: rgb(170,170) 1px solid; padding-top: 5px">选取 ottom: rgb(170,170) 1px solid; border-left: rgb(170,170) 1px solid; padding-bottom: 6px; background-color: rgb(239,239,239); margin: 0px; padding-left: 6px; padding-right: 15px; vertical-align: text-top; border-top: rgb(170,170) 1px solid; padding-top: 6px">ottom: rgb(170,170) 1px solid; padding-top: 6px">$("#lastname")ottom: rgb(170,170) 1px solid; padding-top: 6px">id="lastname" 的元素ottom: 0px; border-left: 0px; padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; border-top: 0px; border-right: 0px; padding-top: 0px"> ottom: rgb(170,170) 1px solid; padding-top: 6px">ottom: rgb(170,170) 1px solid; padding-top: 6px">$(".intro")ottom: rgb(170,170) 1px solid; padding-top: 6px">所有 class="intro" 的元素ottom: 0px; border-left: 0px; padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; border-top: 0px; border-right: 0px; padding-top: 0px"> ottom: rgb(170,170) 1px solid; padding-top: 6px">ottom: rgb(170,170) 1px solid; padding-top: 6px">$("p")ottom: rgb(170,170) 1px solid; padding-top: 6px">所有

元素ottom: 0px; border-left: 0px; padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; border-top: 0px; border-right: 0px; padding-top: 0px">

ottom: rgb(170,170) 1px solid; padding-top: 6px">.ottom: 0px; border-left: 0px; padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; border-top: 0px; border-right: 0px; padding-top: 0px">class.ottom: 0px; border-left: 0px; padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; border-top: 0px; border-right: 0px; padding-top: 0px">classottom: rgb(170,170) 1px solid; padding-top: 6px">$(".intro.demo")ottom: rgb(170,170) 1px solid; padding-top: 6px">所有 class="intro" 且 class="demo" 的元素ottom: 0px; border-left: 0px; padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; border-top: 0px; border-right: 0px; padding-top: 0px"> ottom: rgb(170,170) 1px solid; padding-bottom: 6px; background-color: rgb(255,255,255); margin: 0px; padding-left: 6px; padding-right: 15px; vertical-align: text-top; border-top: rgb(170,170) 1px solid; padding-top: 6px">ottom: rgb(170,170) 1px solid; padding-top: 6px">ottom: 0px; border-left: 0px; padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; border-top: 0px; border-right: 0px; padding-top: 0px"> ottom: rgb(170,170) 1px solid; padding-top: 6px"> 元素ottom: rgb(170,170) 1px solid; padding-top: 6px">$("p:last")ottom: rgb(170,170) 1px solid; padding-top: 6px">最后一个

元素ottom: 0px; border-left: 0px; padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; border-top: 0px; border-right: 0px; padding-top: 0px">

ottom: rgb(170,170) 1px solid; padding-top: 6px">ottom: rgb(170,170) 1px solid; padding-top: 6px">$("tr:odd")ottom: rgb(170,170) 1px solid; padding-top: 6px">所有奇数 ottom: 0px; border-left: 0px; padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; border-top: 0px; border-right: 0px; padding-top: 0px"> ottom: rgb(170,170) 1px solid; padding-top: 6px">)ottom: rgb(170,170) 1px solid; padding-top: 6px">$("ul li:eq(3)")ottom: rgb(170,170) 1px solid; padding-top: 6px">列表中的第四个元素(index 从 0 开始)ottom: 0px; border-left: 0px; padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; border-top: 0px; border-right: 0px; padding-top: 0px"> ottom: rgb(170,170) 1px solid; padding-top: 6px">)ottom: rgb(170,170) 1px solid; padding-top: 6px">$("ul li:gt(3)")ottom: rgb(170,170) 1px solid; padding-top: 6px">列出 index 大于 3 的元素ottom: 0px; border-left: 0px; padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; border-top: 0px; border-right: 0px; padding-top: 0px"> ottom: rgb(170,170) 1px solid; padding-top: 6px">)ottom: rgb(170,170) 1px solid; padding-top: 6px">$("ul li:lt(3)")ottom: rgb(170,170) 1px solid; padding-top: 6px">列出 index 小于 3 的元素ottom: 0px; border-left: 0px; padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; border-top: 0px; border-right: 0px; padding-top: 0px"> ottom: rgb(170,170) 1px solid; padding-top: 6px">:not(ottom: 0px; border-left: 0px; padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; border-top: 0px; border-right: 0px; padding-top: 0px">selector)ottom: rgb(170,170) 1px solid; padding-top: 6px">$("input:not(:empty)")ottom: rgb(170,170) 1px solid; padding-top: 6px">所有不为空的 input 元素ottom: 0px; border-left: 0px; padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; border-top: 0px; border-right: 0px; padding-top: 0px"> ottom: rgb(170,170) 1px solid; padding-top: 6px"> -
ottom: rgb(170,170) 1px solid; padding-top: 6px">所有动画元素ottom: 0px; border-left: 0px; padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; border-top: 0px; border-right: 0px; padding-top: 0px">
ottom: rgb(170,170) 1px solid; padding-top: 6px">)ottom: rgb(170,170) 1px solid; padding-top: 6px">$(":contains('W3School')")ottom: rgb(170,170) 1px solid; padding-top: 6px">包含指定字符串的所有元素ottom: 0px; border-left: 0px; padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; border-top: 0px; border-right: 0px; padding-top: 0px"> ottom: rgb(170,170) 1px solid; padding-top: 6px"> 元素ottom: rgb(170,170) 1px solid; padding-top: 6px">$("table:visible")ottom: rgb(170,170) 1px solid; padding-top: 6px">所有可见的表格ottom: 0px; border-left: 0px; padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; border-top: 0px; border-right: 0px; padding-top: 0px"> ottom: rgb(170,170) 1px solid; padding-top: 6px">s1,s2,s3ottom: rgb(170,170) 1px solid; padding-top: 6px">$("th,td,.intro")ottom: rgb(170,170) 1px solid; padding-top: 6px">所有带有匹配选择的元素ottom: 0px; border-left: 0px; padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; border-top: 0px; border-right: 0px; padding-top: 0px"> ottom: rgb(170,170) 1px solid; padding-top: 6px">]ottom: rgb(170,170) 1px solid; padding-top: 6px">$("[href]")ottom: rgb(170,170) 1px solid; padding-top: 6px">所有带有 href 属性的元素ottom: 0px; border-left: 0px; padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; border-top: 0px; border-right: 0px; padding-top: 0px"> ottom: rgb(170,170) 1px solid; padding-top: 6px">=]ottom: rgb(170,170) 1px solid; padding-top: 6px">$("[href='#']")ottom: rgb(170,170) 1px solid; padding-top: 6px">所有 href 属性的值等于 "#" 的元素ottom: 0px; border-left: 0px; padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; border-top: 0px; border-right: 0px; padding-top: 0px"> ottom: rgb(170,170) 1px solid; padding-top: 6px">!=]ottom: rgb(170,170) 1px solid; padding-top: 6px">$("[href!='#']")ottom: rgb(170,170) 1px solid; padding-top: 6px">所有 href 属性的值不等于 "#" 的元素ottom: 0px; border-left: 0px; padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; border-top: 0px; border-right: 0px; padding-top: 0px"> ottom: rgb(170,170) 1px solid; padding-top: 6px">$=]ottom: rgb(170,170) 1px solid; padding-top: 6px">$("[href$='.jpg']")ottom: rgb(170,170) 1px solid; padding-top: 6px">所有 href 属性的值包含以 ".jpg" 结尾的元素ottom: 0px; border-left: 0px; padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; border-top: 0px; border-right: 0px; padding-top: 0px"> ottom: rgb(170,170) 1px solid; padding-top: 6px"> 元素ottom: rgb(170,170) 1px solid; padding-top: 6px">$(":text")ottom: rgb(170,170) 1px solid; padding-top: 6px">所有 type="text" 的 元素ottom: 0px; border-left: 0px; padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; border-top: 0px; border-right: 0px; padding-top: 0px"> ottom: rgb(170,170) 1px solid; padding-top: 6px"> 元素ottom: rgb(170,170) 1px solid; padding-top: 6px">$(":radio")ottom: rgb(170,170) 1px solid; padding-top: 6px">所有 type="radio" 的 元素ottom: 0px; border-left: 0px; padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; border-top: 0px; border-right: 0px; padding-top: 0px"> ottom: rgb(170,170) 1px solid; padding-top: 6px"> 元素ottom: rgb(170,170) 1px solid; padding-top: 6px">$(":submit")ottom: rgb(170,170) 1px solid; padding-top: 6px">所有 type="submit" 的 元素ottom: 0px; border-left: 0px; padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; border-top: 0px; border-right: 0px; padding-top: 0px"> ottom: rgb(170,170) 1px solid; padding-top: 6px"> 元素ottom: rgb(170,170) 1px solid; padding-top: 6px">$(":button")ottom: rgb(170,170) 1px solid; padding-top: 6px">所有 type="button" 的 元素ottom: 0px; border-left: 0px; padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; border-top: 0px; border-right: 0px; padding-top: 0px"> ottom: rgb(170,170) 1px solid; padding-top: 6px"> 元素ottom: rgb(170,170) 1px solid; padding-top: 6px">$(":file")ottom: rgb(170,170) 1px solid; padding-top: 6px">所有 type="file" 的 元素ottom: 0px; border-left: 0px; padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; border-top: 0px; border-right: 0px; padding-top: 0px"> ottom: rgb(170,170) 1px solid; padding-top: 6px">ottom: rgb(170,170) 1px solid; padding-top: 6px">$(":disabled")ottom: rgb(170,170) 1px solid; padding-top: 6px">所有禁用的 input 元素ottom: 0px; border-left: 0px; padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; border-top: 0px; border-right: 0px; padding-top: 0px"> ottom: rgb(170,170) 1px solid; padding-top: 6px">ottom: rgb(170,170) 1px solid; padding-top: 6px">$(":checked")ottom: rgb(170,170) 1px solid; padding-top: 6px">所有被选中的 input 元素

原文地址:https://www.jb51.cc/jquery/51347.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐