jQuery pierwsze dziecko „tego”

317

Próbuję przekazać „to” z zakresu kliknięcia do funkcji jQuery, która może następnie wykonać jQuery na pierwszym elemencie potomnym tego klikniętego elementu. Wydaje się, że nie mogę tego zrobić poprawnie ...

<p onclick="toggleSection($(this));"><span class="redClass"></span></p>

JavaScript:

function toggleSection(element) {
  element.toggleClass("redClass");
}

Jak odwołać się do: first-child elementu?

macca1
źródło
4
Jeśli używasz jQuery, dlaczego nie powiążesz programów obsługi zdarzeń za pomocą jQuery?
Vivin Paliath,
2
ponieważ procedury obsługi zdarzeń wiązania muszą zostać zainicjowane w document.ready (), która dodaje działanie zwiększające wydajność (jest to aplikacja dla IE6). czy jest inny sposób?
macca1
Hm .. nie jestem pewien. Wiązanie za pomocą jQuery jest standardowym sposobem (jeśli już używasz jQuery). Jakiego rodzaju wydajności odczuwasz podczas korzystania jQuery(document).ready(...)?
Vivin Paliath,
To duża aplikacja z programistami 7+. Początkowo minęły ponad 4 sekundy, zanim spróbowałem go trochę wyczyścić. Wolę więc unikać dodawania do niej więcej, gdy nie muszę :)
macca1

Odpowiedzi:

482

Jeśli chcesz zastosować selektor do kontekstu dostarczonego przez istniejący zestaw jQuery, spróbuj funkcji find () :

element.find(">:first-child").toggleClass("redClass");

Jørn Schou-Rode zauważył, że prawdopodobnie chcesz tylko znaleźć pierwszego bezpośredniego potomka elementu kontekstu, stąd selektor potomny (>). Wskazuje również, że równie dobrze możesz użyć funkcji children () , która jest bardzo podobna do find (), ale przeszukuje tylko jeden poziom głęboko w hierarchii (co jest wszystkim, czego potrzebujesz ...):

element.children(":first").toggleClass("redClass");
Shog9
źródło
1
dzięki! działa świetnie. Wyobrażam sobie, że inne sposoby wymienione poniżej również będą działać.
macca1
6
Wierzę, że find()przeszukuje wszystkich potomków i :first-childmogę dopasować jeden element na rodzica. Dlatego zapytanie może zwrócić kilka elementów. Czy się mylę?
Jørn Schou-Rode
19
Wiem, że to stare pytanie / odpowiedź, ale użycie selektora „>” bez rodzica w tym selektorze jest amortyzowane (na przykład „>: firstchild”) od jQuery 1.8. Zamiast tego sugeruję użycie element.children(":first-child")lubelement.children().first();
Kevin B
3
@KevinB najwyraźniej zdecydowali się jednak nie wycofywać
Alnitak
1
najlepszym podejściem byłoby NIE powtarzanie wszystkich elementów, a następnie wybieranie pierwszego, jak sugerują niektórzy. To byłoby ZŁE.
vsync
74

Użyj childrenfunkcji z :firstselektora , aby uzyskać jednolity pierwsze dziecko element:

element.children(":first").toggleClass("redClass");
Jørn Schou-Rode
źródło
element.children () [0] .toggleClass („redClass”);
Zakos
5
@Zakos:TypeError: Object [object HTMLAnchorElement] has no method 'toggleClass'
Jørn Schou-Rode
51

Dodałem jsperf test, aby zobaczyć różnicę prędkości na różne sposoby, aby uzyskać pierwsze dziecko (w sumie ponad 1000 dzieci)

dany, notif = $('#foo')

jQuery sposoby:

  1. $(":first-child", notif) - 4 304 operacji / s - najszybciej
  2. notif.children(":first") - 653 operacji / s - 85% wolniej
  3. notif.children()[0] - 1416 operacji / s - 67% wolniej

Rodzime sposoby:

  1. JavaScript native ” ele.firstChild- 4 934 323 operacji / s (wszystkie powyższe podejścia są o 100% wolniejsze w porównaniu do firstChild)
  2. Natywne elementy DOM z jQery: notif[0].firstChild- 4913658 operacji / sek

Tak więc pierwsze 3 podejścia jQuery nie są zalecane, przynajmniej dla pierwszego dziecka (wątpię, by tak było w przypadku wielu innych). Jeśli masz obiekt jQuery i potrzebujesz pierwszego dziecka, pobierz natywny element DOM z obiektu jQuery, korzystając z odwołania do tablicy [0] (zalecane) lub .get(0)użyj ele.firstChild. Daje to takie same wyniki jak w zwykłym użyciu JavaScript.

wszystkie testy są wykonywane w wersji Chrome Canary v15.0.854.0

manikanta
źródło
20
W rzeczywistości firstChildnie da takich samych wyników jak children()zapytania jQuery lub selektora. firstChildbędzie zawierać węzły tekstowe, które są rzadko pożądane. jQuery contents()funkcja będzie włączyć je, ale children()nie będzie. Nowsze przeglądarki obsługują firstElementChildpierwszy element potomny, ale IE <9 go nie obsługuje. Tak więc, jeśli używasz firstChild, musisz ręcznie znaleźć pierwsze potomne węzły nietekstowe.
Maks.
1
$(":first-child", notif)powinno być $(":first", notif)dla oczekiwanego zachowania. Pierwszy zwróci wszystkich potomków pierworodnych.
Drazen Bjelovuk
18
element.children().first();

Znajdź wszystkie dzieci i zdobądź je pierwsze.

Bishal Paudel
źródło
1
Zdecydowanie najprostsza metoda i bardziej wydajna niż .children(':first').
Gras Double
3
Jak to jest bardziej wydajne? Wydaje się, że bierze wszystkie dzieci, a następnie bierze pierwsze, a nie tylko pierwsze dziecko.
Anthony McGrath
9

Czy próbowałeś

$(":first-child", element).toggleClass("redClass");

Myślę, że chcesz ustawić swój element jako kontekst wyszukiwania. Może istnieć lepszy sposób na zrobienie tego, który wskoczy tu inny guru jQuery i rzuci na ciebie :)

theIV
źródło
3
to się nie powiedzie, jeśli elementma
wnuki
4

Właśnie napisałem wtyczkę, która używa, .firstElementChildjeśli to możliwe, i w razie potrzeby wraca do iteracji po każdym węźle:

(function ($) {
    var useElementChild = ('firstElementChild' in document.createElement('div'));

    $.fn.firstChild = function () {
        return this.map(function() {
            if (useElementChild) {
                return this.firstElementChild;
            } else {
                var node = this.firstChild;
                while (node) {
                    if (node.type === 1) {
                        break;
                    }
                    node = node.nextSibling;
                }
                return node;
            }
        });
    };
})(jQuery);

Nie jest tak szybki jak czyste rozwiązanie DOM, ale w testach jsperf pod Chrome 24 był on o kilka rzędów wielkości szybszy niż jakakolwiek inna metoda oparta na selektorze jQuery.

Alnitak
źródło
1
Podoba mi się ta wtyczka - ale są 2 problemy: 1) Skrypt wtyczki nie może zostać dołączony do głowy, ponieważ document.bodynie został jeszcze zainicjowany, 2) Wydajność jest tylko znacznie lepsza niż alternatywy, jeśli liczba węzłów potomnych jest bardzo wysoka. Tylko dla kilku dzieci (powiedzmy mniej niż 10) $('>:first-child',context)jest to trochę szybsze. Tylko liczba dzieci wpływa na wydajność, a nie głębokość.
codefactor
@codefactor dobra uwaga na temat document.body- przyjrzę się temu.
Alnitak,
4

możesz użyć DOM

$(this).children().first()
// is equivalent to
$(this.firstChild)
Yukulélé
źródło
1

użyj go w ten sposób, aby najpierw nadać nazwę klasie, aby oznaczyć p, np. „myp”

następnie użyj następującego kodu

$(document).ready(function() {
    $(".myp").click(function() {
        $(this).children(":first").toggleClass("classname"); // this will access the span.
    })
})
Vishal Gupta
źródło
-3

Jeśli chcesz natychmiastowe pierwsze dziecko, potrzebujesz

    $(element).first();

Jeśli chcesz konkretnego pierwszego elementu w domie od swojego elementu, użyj go poniżej

    var spanElement = $(elementId).find(".redClass :first");
    $(spanElement).addClass("yourClassHere");

wypróbuj: http://jsfiddle.net/vgGbc/2/

Amit Rathod
źródło
11
jest to po prostu złe - jeśli elementjest to węzeł DOM, to $(element).first()jest on równoważny $(element), a nie jego pierwszemu potomkowi.
Alnitak
1
Zgadzam się, jeśli element jest węzłem DOM $ (element). First () jest równoważny $ (element), to spowodowało problem z nokautem
JS