jQuery primer hijo de "esto"


317

Estoy tratando de pasar "esto" de un intervalo de clics a una función jQuery que luego puede ejecutar jQuery en el primer elemento secundario de ese elemento cliqueado. Parece que no puedo hacerlo bien ...

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

Javascript:

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

¿Cómo hago referencia al elemento: first-child of?


44
Si está utilizando jQuery, ¿por qué no vincula los controladores de eventos con jQuery también?
Vivin Paliath

2
porque los controladores de eventos de vinculación deben inicializarse en document.ready () que agrega un impacto en el rendimiento (esta es una aplicación para IE6). ¿O hay otra manera?
macca1

Hm ... no estoy seguro. La vinculación con jQuery es la forma estándar (si ya está usando jQuery). ¿Qué tipo de éxito en el rendimiento experimentas cuando lo usas jQuery(document).ready(...)?
Vivin Paliath

Es una gran aplicación con más de 7 desarrolladores. Originalmente pasaron más de 4 segundos antes de que intentara limpiarlo un poco. Así que prefiero evitar añadir más a él cuando yo no tengo que :)
macca1

Respuestas:


482

Si desea aplicar un selector al contexto proporcionado por un conjunto jQuery existente, pruebe la función find () :

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

Jørn Schou-Rode señaló que probablemente solo desee encontrar el primer descendiente directo del elemento de contexto, de ahí el selector secundario (>). También señala que también podría usar la función children () , que es muy similar a find () pero solo busca un nivel en la jerarquía (que es todo lo que necesita ...):

element.children(":first").toggleClass("redClass");

1
¡Gracias! funciona perfectamente. Me imagino que las otras formas enumeradas a continuación también funcionarán.
macca1

66
Creo que find()busca en todos los descendientes y :first-childpuede coincidir con un elemento por padre. Por lo tanto, esta consulta puede devolver varios elementos. ¿O me equivoco?
Jørn Schou-Rode

19
Sé que esta es una vieja pregunta / respuesta, pero el uso del selector ">" sin un padre en ese selector se deprecia (por ejemplo, ">: primer hijo") a partir de jQuery 1.8. Sugiero usar element.children(":first-child")oelement.children().first();
Kevin B

3
@KevinB aparentemente decidieron no desaprobarlo después de todo
Alnitak

1
el mejor enfoque sería NO iterar en todos los elementos y luego elegir el primero, como algunos sugirieron aquí. Esto sería MALO.
vsync


51

He agregado la prueba jsperf para ver la diferencia de velocidad para diferentes enfoques para obtener el primer hijo (un total de más de 1000 niños)

dado, notif = $('#foo')

Formas jQuery:

  1. $(":first-child", notif) - 4,304 operaciones / seg - más rápido
  2. notif.children(":first") - 653 operaciones / seg. - 85% más lento
  3. notif.children()[0] - 1,416 operaciones / seg. - 67% más lento

Maneras nativas:

  1. JavaScript nativo ' ele.firstChild: 4.934.323 operaciones / segundo (todos los enfoques anteriores son 100% más lentos en comparación con firstChild)
  2. DOM nativo de jQery: notif[0].firstChild- 4,913,658 operaciones / seg.

Por lo tanto, no se recomiendan los primeros 3 enfoques jQuery, al menos para el primer hijo (dudo que ese sea el caso con muchos otros también). Si tiene un objeto jQuery y necesita obtener el primer hijo, obtenga el elemento DOM nativo del objeto jQuery, utilizando la referencia de matriz [0] (recomendado) o .get(0)use el ele.firstChild. Esto proporciona los mismos resultados idénticos que el uso regular de JavaScript.

todas las pruebas se realizan en Chrome Canary build v15.0.854.0


20
En realidad, firstChildno dará los mismos resultados que las children()consultas de jQuery o del selector. firstChildincluirá nodos de texto que rara vez se desea. jQuery contents()función se incluyen, pero children()no lo hará. Los navegadores más nuevos admiten firstElementChildlo que dará el primer elemento hijo, pero IE <9 no lo admite. Entonces, si lo usa firstChild, tiene que encontrar manualmente el primer nodo secundario que no es de texto.
Max

1
$(":first-child", notif)debe ser $(":first", notif)por el comportamiento esperado. El primero devolverá todos los descendientes del primer elemento secundario.
Drazen Bjelovuk

18
element.children().first();

Encuentre a todos los niños y obtenga el primero de ellos.


1
Con mucho, el método más simple y más eficiente que .children(':first').
Gras Double

3
¿Cómo es más eficiente? Parece que atrae a todos los niños, luego toma el primero, en lugar de obtener solo el primer hijo.
Anthony McGrath

9

Has probado

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

Creo que desea establecer su elemento como contexto para su búsqueda. Puede haber una mejor manera de hacer esto que algún otro gurú de jQuery saltará aquí y te arrojará :)


3
esto fallará si elementtiene nietos
Alnitak

4

Acabo de escribir un complemento que usa .firstElementChildsi es posible, y recurre a iterar sobre cada nodo individual si es necesario:

(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);

No es tan rápido como una solución DOM pura, pero en las pruebas jsperf en Chrome 24 fue un par de órdenes de magnitud más rápido que cualquier otro método basado en el selector jQuery.


1
Me gusta este complemento, pero hay 2 problemas: 1) El script del complemento no se puede incluir en el encabezado porque document.bodyaún no se ha inicializado, 2) El rendimiento solo es mucho mejor que las alternativas si el número de nodos secundarios es muy alto. Para solo unos pocos niños (digamos menos de 10) $('>:first-child',context)es un poco más rápido. Solo el número de niños afecta el rendimiento, no la profundidad.
codefactor

@codefactor buen punto sobre document.body- Lo investigaré.
Alnitak

4

puedes usar DOM

$(this).children().first()
// is equivalent to
$(this.firstChild)


1

úsalo como esto primero, dale un nombre de clase a la etiqueta p como "myp"

luego en usar el siguiente código

$(document).ready(function() {
    $(".myp").click(function() {
        $(this).children(":first").toggleClass("classname"); // this will access the span.
    })
})

-3

Si quieres un primer hijo inmediato, necesitas

    $(element).first();

Si desea un primer elemento particular en el dom de su elemento, use a continuación

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

probar: http://jsfiddle.net/vgGbc/2/


11
esto es simplemente incorrecto: si elementes un nodo DOM, $(element).first()es equivalente a $(element), no su primer hijo.
Alnitak

1
De acuerdo, si el elemento es un nodo DOM $ (element) .first () es equivalente $ (element) esto me causó problemas con el enlace knockoutJS
drgn
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.