Development Tip

다음 일치하는 형제를 찾는 효율적이고 간결한 방법?

yourdevel 2020. 10. 19. 12:52
반응형

다음 일치하는 형제를 찾는 효율적이고 간결한 방법?


공식 jQuery API를 고수 nextAll하면 :first의사 클래스 와 함께 사용 하는 것 외에 주어진 선택자와 일치하는 요소의 다음 형제를 찾는 더 간결하지만 덜 효율적이지 않은 방법이 있습니까?

내가 공식 API라고 말하면 내부를 해킹하지 않고 Sizzle으로 바로 이동하고 믹스에 플러그인을 추가하는 등의 작업을 의미합니다. (내가 그렇게해야한다면 그렇게 되겠지만이 질문은 그게 아닙니다. )

예를 들어 다음과 같은 구조가 있습니다.

<div>One</div>
<div class='foo'>Two</div>
<div>Three</div>
<div class='foo'>Four</div>
<div>Five</div>
<div>Six</div>
<div>Seven</div>
<div class='foo'>Eight</div>

나는이있는 경우 divthis(아마도에서 click무엇이든, 핸들러)와 선택 "div.foo"를 일치하는 다음 형제 사업부를 찾으려면,이 작업을 수행 할 수 있습니다 :

var nextFoo = $(this).nextAll("div.foo:first");

... 그리고 작동합니다 (예를 들어 "Five"로 시작하면 "Six"와 "Seven"을 건너 뛰고 "Eight"를 찾습니다).)하지만 투박하고 첫 번째 항목과 일치 시키려면 선택자가 여러 개 있으면 훨씬 복잡해집니다. (부여, 그것은의 많은 루프가 될 것 원시 DOM보다 더의 간결은 ...)

나는 기본적으로 원한다 :

var nextFoo = $(this).nextMatching("div.foo");

... nextMatching모든 범위의 선택자를 사용할 수 있습니다. 나는 항상 next(selector)이것을하지 않는다는 것에 놀랐지 만 그렇지 않습니다. 그리고 문서는 그것이하는 일에 대해 분명합니다.

항상 작성하고 추가 할 수 있지만 그렇게하고 게시 된 API를 고수하면 상황이 상당히 비효율적입니다. 예를 들어, 순진한 next루프 :

jQuery.fn.nextMatching = function(selector) {
    var match;

    match = this.next();
    while (match.length > 0 && !match.is(selector)) {
        match = match.next();
    }
    return match;
};

... 보다 현저히 느립니다nextAll("selector:first") . 그리고 그것은 놀라운 일이 아닙니다 nextAll. 모든 것을 Sizzle에 넘길 수 있으며 Sizzle은 완전히 최적화되었습니다. 위의 순진한 루프는 모든 종류의 임시 객체를 만들고 버리며 매번 선택기를 다시 구문 분석해야합니다. 느리다는 것은 놀라운 일이 아닙니다.

물론 :first끝까지 던질 수는 없습니다 .

jQuery.fn.nextMatching = function(selector) {
    return this.nextAll(selector + ":first"); // <== WRONG
};

... 왜냐하면 "div.foo"와 같은 간단한 선택자에서는 작동하지만 "div.foo, div.bar"와 같이 내가 말한 "여러 가지 중 하나"옵션에서는 실패합니다.

편집 : 죄송합니다. 마지막으로 결과 .nextAll()사용 하고 사용할 수 .first()있지만 jQuery는 첫 번째 형제를 찾기 위해 모든 형제를 방문해야합니다. 전체 목록을 살펴 보지 않고 일치하는 경우 중지하여 모든 결과를 버리고 첫 번째 결과 만 버리고 싶습니다. ( 정말 빠르게 발생하는 것처럼 보이지만 앞서 링크 된 속도 비교 에서 마지막 테스트 사례를 참조하십시오 .)

미리 감사드립니다.


다음 같이 다중 선택기전달 하고 결과에 .nextAll()사용할 수 있습니다 .first().

var nextFoo = $(this).nextAll("div.foo, div.something, div.else").first();

편집 : 비교를 위해 여기에 테스트 스위트에 추가됩니다. http://jsperf.com/jquery-next-loop-vs-nextall-first/2 이 접근 방식은 .nextAll().... 네이티브 코드 가능 (모든 현재 브라우저) 그냥 결과 집합의 첫 번째를 복용 오프 선택 방법을 빨리 당신이 자바 스크립트에서 순수 할 수있는 루핑 어떤 것보다.


방법을 사용하는 first방법 :

jQuery.fn.nextMatching = function(selector) {
    return this.nextAll(selector).first();
}

편집, 업데이트

활용 ( "이전 ~ 형제") 다음 형제 선택기를

jQuery.fn.nextMatching = function nextMatchTest(selector) {
     return $("~ " + selector, this).first()
};

http://jsperf.com/jquery-next-loop-vs-nextall-first/10

jQuery.fn.nextMatching = function nextMatchTest(selector) {
     return $("~ " + selector, this).first()
};
   var nextFoo = $("div:first").nextMatchTest("div.foo");
   console.log(nextFoo)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div>One</div>
<div class='foo'>Two</div>
<div>Three</div>
<div class='foo'>Four</div>
<div>Five</div>
<div>Six</div>
<div>Seven</div>
<div class='goo'>Eight</div>


Note, Not yet added to or tried at comparison test. Not certain if actually more efficient than .nextAll() implementation. Piece attempts to parse selector string argument having multiple comma-separated selector's . Returns .first() element of single or comma-separated selectors provided as argument , or this element if no selector argument provided to .nextMatchTest(). Appear to return same results at chrome 37 , ie11

v2

$.fn.nextMatching = function (selector) {
    var elem = /,/.test(selector) ? selector.split(",") : selector
    , sel = this.selector
    , ret = $.isArray(elem) ? elem.map(function (el) {
        return $(sel + " ~ " + $(el).selector).first()[0]
    }) : $(sel + " ~ " + elem).first();
    return selector ? $(ret) : this
};

$.fn.nextMatching = function (selector) {
    var elem = /,/.test(selector) ? selector.split(",") : selector
    , sel = this.selector
    , ret = $.isArray(elem) ? elem.map(function (el) {
        return $(sel + " ~ " + $(el).selector).first()[0]
    }) : $(sel + " ~ " + elem).first();
    return selector ? $(ret) : this
};

var div = $("div:first")
    , foo = div.nextMatching()
    , nextFoo = div.nextMatching("div.foo")
    , nextFooMultiple = div.nextMatching("div.foo, div.goo");
nextFooMultiple.css("color", "green");
nextFoo.css("color", "blue");
console.log(foo);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div>One</div>
<div class='foo'>Two</div>
<div>Three</div>
<div class='foo'>Four</div>
<div>Five</div>
<div>Six</div>
<div>Seven</div>
<div class='goo'>Eight</div>

참고URL : https://stackoverflow.com/questions/4933236/efficient-concise-way-to-find-next-matching-sibling

반응형