Jquery 1.9.1 소스 코드 분석 시리즈 필터링 작업

PHPz
풀어 주다: 2018-10-13 16:22:33
원래의
1083명이 탐색했습니다.

더 이상 고민하지 않고 바로 본론으로 들어가겠습니다.

jQuery.fn.find( selector )
로그인 후 복사

find는 매개변수 표현식 선택기(선택기(문자열), DOM 요소(요소), jQuery 객체)를 허용합니다.

두 가지 상황으로 처리됩니다.

첫 번째, 들어오는 매개 변수가 문자열이 아닌 경우 먼저 jQuery 선택기를 통해 선택기를 찾은 다음 현재에 포함된 일치 항목을 필터링합니다. jQuery 객체. 요소의 노드입니다.
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)를 호출하여 직접 처리합니다
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;
로그인 후 복사
jQuery.fn.closest( selectors, context )
로그인 후 복사


두 번째 매개변수는 선택사항입니다. 이 함수는 현재 일치하는 요소부터 시작하여 지정된 표현식과 일치하는 첫 번째 요소를 선택하고 이를 jQuery 개체 형식으로 반환하는 데 사용됩니다.

여기서 표현식에는 선택기(문자열), DOM 요소(요소) 및 jQuery 객체가 포함됩니다.

코드의 처리 단계는

pos = rneedsContext.test( selectors ) || typeof selectors !== "string" ?
jQuery( selectors, context || this.context ) :
0;
로그인 후 복사
1입니다. 먼저 전달된 매개변수에 따라 결과를 쿼리하고 pos에 저장합니다.

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 );
로그인 후 복사
2. 현재 jQuery 개체의 각 요소를 탐색합니다. 이 요소부터 시작하여 지정된 표현식과 일치하는 첫 번째 상위 요소를 단계별로 선택합니다.


parents() 및 .closest() 메소드는 둘 다 DOM 트리를 순회한다는 점에서 유사합니다. 그러나 그 차이도 매우 큽니다. 가장 가까운 것이 조건을 충족하는 첫 번째 집합을 찾고 이를 종료합니다. 부모는 조건을 충족하는 모든 집합을 찾습니다.

jQuery.fn.parent/ parent/ parentUntil/ next/ prev/ nextAll/ prevAll/ nextUntil/ prevUntil/ siblings/ children/ 내용 상세 설명

위 그룹 의 필터를 함께 처리하면 소스코드는 다음과 같습니다
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, i, until ) {…},
  prevUntil: function( elem, i, until ) {…},
  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 );
  };
 });
로그인 후 복사


이러한 필터링 단계가 일관됨을 알 수 있습니다. 현재 jQuery 객체의 각 매칭 요소는 먼저 map 함수를 통해 해당 매칭 함수(fn)에 대입되어 결과를 얻은 후 후속 필터링이 수행됩니다.

먼저 후속 필터링을 살펴보겠습니다(대체 시드 ret은 jQuery.map(this, fn, Until )을 통해 얻었습니다)
if ( !runtil.test( name ) ) {
 selector = until;
}
로그인 후 복사
우선 모든 필터링 기능이 Until 이 매개변수는 Until으로 끝나는 여러 필터에만 필요합니다. 다른 필터에는 selector 매개변수만 있습니다.

if ( selector && typeof selector === "string" ) {
 ret = jQuery.filter( selector, ret );
}
로그인 후 복사
둘째, 선택자가 있으면 이전 검색결과를 선택자 ret을 통해 필터링합니다

ret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret;
로그인 후 복사
그러면 eedUnique가 보장됩니다. 필터링 조건은 여러 가지(children/contents/next/prev)가 있습니다. 현재 jQuery 객체와 일치하는 요소의 개수가 여러 개인 경우, 일치하는 각 요소를 통해 얻은 결과는 결과 집합 ret에 저장되며 가중치를 제거할 필요가 없습니다. . 다른 검사를 수행해야 합니다. jQuery.unique 메소드에 대한 자세한 설명을 보려면 클릭하세요

if ( this.length > 1 && rparentsprev.test( name ) ) {
 ret = ret.reverse();
}
로그인 후 복사
또한 처리해야 하는 특수한 경우는 다음과 같습니다. 현재 jQuery와 일치하는 요소가 여러 개 있는 경우 개체, 상위 /prevUntil / prevAll 사용 이 세 가지 필터의 결과는 역순으로 정렬되어야 합니다. 역순이 필요한 이유: jQuery.unique는 Sizzle 엔진에서 정렬 기능인 Sizzle .uniqueSort를 사용합니다. 이 정렬 기능은 문서의 맨 위 개체부터 맨 아래 개체까지 개체를 정렬합니다.

return this.pushStack( ret ); 
로그인 후 복사
마지막으로 패키징된 결과를 반환합니다


위에서 테마의 프레임워크 구조를 언급했는데 이에 대해 이야기해보겠습니다. 그룹 필터 매칭 함수에 사용된 jQuery.dir, jQuery.sibling 두 함수는 소스코드로 직접 이동

// 현재 요소인 elem에 지정된 dir에 해당하는 노드부터 dir을 검색하여 이 노드들을 저장한다. 루프가 종료될 때까지 일치합니다.
참고: 결과에는 요소 노드가 포함되지 않습니다.
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;
 } 
로그인 후 복사
jQuery.fn.add( selector, context )和jQuery.fn. addBack( selector )
로그인 후 복사

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, selector, true) );
},
로그인 후 복사
add 함수는 지정된 표현식을 현재 일치 항목에 추가합니다. element 수식의 요소이며 jQuery 객체로 반환됩니다. add는 선택기(문자열), HTML 콘텐츠(문자열), DOM 요소(요소) 및 jQuery 객체를 받을 수 있습니다. 처리는 상대적으로 간단합니다. 소스 코드로 이동하면 됩니다.

not과 filter는 둘 다 작업 자체의 컬렉션입니다. not은 컬렉션 자체의 항목을 필터링하는 것입니다. 필터링 조건 선택기를 충족하고 다른 항목은 그대로 둡니다. 필터는 필터 조건 선택기를 만족하는 항목을 남기는 것입니다.

핵심은 winnow(elements, qualifier, keep) 함수입니다. 이 기능의 기능은 동일한 필터링 또는 비필터링 기능을 수행하는 것입니다. 필터 조건 한정자에는 함수, DOM 노드, 문자열의 세 가지 유형이 있습니다. keep: true는 필터 조건을 충족하는 항목을 유지한다는 의미이고, false는 필터 조건을 충족하지 않는 항목을 유지한다는 의미입니다.
//执行相同的过滤或者不过滤的功能
function winnow( elements, qualifier, keep ) {
 // Can&#39;t pass null or undefined to indexOf in Firefox 4
 // Set to 0 to skip string check
 qualifier = qualifier || 0;
 //如果过滤条件是函数,则通过过滤函数过滤
 if ( jQuery.isFunction( qualifier ) ) {
  return jQuery.grep(elements, function( elem, i ) {
   var retVal = !!qualifier.call( elem, i, elem );
   return retVal === keep;
  });
 //如果过滤条件是DOM相关类型,通过比较节点是否相同来过滤
 } else if ( qualifier.nodeType ) {
  return jQuery.grep(elements, function( elem ) {
   return ( elem === qualifier ) === keep;
  });
 //如果过滤条件是字符串
 } else if ( typeof qualifier === "string" ) {
  //过滤出elements中的节点元素
  var filtered = jQuery.grep(elements, function( elem ) {
   return elem.nodeType === 1;
  });
  // 其中isSimple = /^.[^:#\[\.,]*$/
  if ( isSimple.test( qualifier ) ) {
   return jQuery.filter(qualifier, filtered, !keep);
  } else {
   //查找filtered中满足筛选条件qualifier的节点
   qualifier = jQuery.filter( qualifier, filtered );
  }
 }
 //过滤出elements中满足过滤条件的元素
 return jQuery.grep(elements, function( elem ) {
  return ( jQuery.inArray( elem, qualifier ) >= 0 ) === keep;
 });
}
로그인 후 복사
winnow의 소스코드 설명은 다음과 같습니다

jQuery.grep을 사용하였으며, grep에 대한 자세한 설명은 여기를 클릭하세요.
jQuery.filter: function( expr, elems, 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 )
로그인 후 복사
jQuery.filter(expr, elems, not) 이 하위 수준 API는 특별히 jQuery.fn.filter의 필터 조건이 문자열인 경우를 처리하는 데 사용됩니다.
<🎜><🎜><🎜>

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

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

if ( !elem ) {
 return ( this[0] && this[0].parentNode ) ? this.first().prevAll().length : -1;
}
로그인 후 복사

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

if ( typeof elem === "string" ) {
 //在数组jQuery( elem )中搜索指定的值,并返回其索引值
 return jQuery.inArray( this[0], jQuery( elem ) );
}
로그인 후 복사

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

return jQuery.inArray(elem.jquery ? elem[0] : elem, this ); 
로그인 후 복사

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

【相关教程推荐】

1. JavaScript视频教程
2. JavaScript在线手册
3. bootstrap教程

관련 라벨:
원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
최신 이슈
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿