2010-10-19 6 views
5

Tengo una estructura de navegación retorcido que se pueden generalizar como:diferencia en los resultados devueltos entre .Tiene() y: tiene()

<ul id="navigation"> 
    <li> 
     A 
     <ul> 
      <li> 
       B 
       <ul> 
        <li>C</li> 
       </ul> 
      </li> 
      <li> 
       D 
       <ul> 
        <li> 
         E 
         <ul> 
          <li>F</li> 
         </ul> 
        </li> 
       </ul> 
      </li> 
     </ul> 
    </li> 
</ul> 

Sub-elementos están ocultos hasta vuelo estacionario. Quiero indicar que B, D y E tienen subtemas labrando ellos, así que utilizan el selector:

$('#navigation > li li:has(ul)') 

Lo que sólo regresaron B y D. Si lo cambia a:

$('#navigation > li li').has('ul') 

devueltos todos los artículos correctos, pero estoy confundido en cuanto a por qué.

EDITAR

:has() no parece ser afectada (enteramente) anidando como

$('#navigation ul > li:has(ul)') 

devuelve los mismos resultados que .has() anteriormente.

+0

Me parece que los resultados deberían ser los mismos. No sé por qué son diferentes. Tal vez Sizzle deja de buscar elementos anidados cuando se encuentra una coincidencia. Si es así, esto parecería ignorar la posibilidad de elementos idénticos anidados (como lo ha hecho en su ejemplo). – user113716

Respuesta

7

De la documentación API jQuery:

:has selecciona elementos que contener al menos un elemento que coincide con el selector especificado.

.has() reduce el conjunto de elementos coincidentes a los que tienen un descendiente que coincide con el selector o elemento de DOM.

Hay una pregunta relacionada aquí: jQuery: subtle difference between .has() and :has(), que parece apuntar a cuál podría ser la diferencia en los dos.

Sin embargo, parece que :has no se ve dentro de un partido en una forma anidada mientras .has() hace porque devuelve un subconjunto de partidos como un objeto jQuery es capaz de igualar todos los descendientes, incluso el anidado, como un regular jQuery selector.

+3

Esas son las descripciones copiadas de los documentos [aquí] (http://api.jquery.com/has-selector/) y [aquí] (http://api.jquery.com/has/). ¿Cómo los hace diferentes? Me parece que deberían devolver los mismos resultados. – user113716

+1

El enlace que ha publicado es específico de un problema en el que el selector comienza con '>'. – user113716

+1

Tengo que estar de acuerdo con @patrick - esto no responde en absoluto a la pregunta, la descripción ': has()' significa que * debería * encontrar ese tercer elemento, 'E'. Además, le gustaría saber de dónde provienen estas descripciones. –

0

El :has() selector selecciona solo aquellos elementos que tienen elementos descendentes que coinciden con el selector dado. Internamente, :has is defined como (Sizzle es jQuery biblioteca selector predeterminado):

function(elem, i, match){ 
    return !!Sizzle(match[3], elem).length; 
} 

Esto es casi equivalente a la prueba jQuery("selector", elem).length o jQuery(elem).find("selector").length para cada elemento seleccionado para filtrar los que no tienen tales descendientes.

En contraste con eso, el has method puede tomar un selector o un elemento DOM y devuelve solo aquellos elementos que no contienen ninguno de los elementos dados. Debido a nivel interno, la has method is defined como:

function(target) { 
    var targets = jQuery(target); 
    return this.filter(function() { 
     for (var i = 0, l = targets.length; i < l; i++) { 
      if (jQuery.contains(this, targets[i])) { 
       return true; 
      } 
     } 
    }); 
} 

por lo que utiliza el contains method para comprobar si los elementos dados están contenidos para filtrar los elementos seleccionados. Tenga en cuenta que es suficiente que solo se contenga uno de los elementos dados.

+1

Esto no explica el comportamiento, sin embargo, este es un error en Sizzle, ya que * debería * devolver estos elementos, el problema es que la matriz de partes del selector se muestra incorrectamente en este escenario. Por ejemplo: '$ ('# navigation li li: has (ul)')' dará 3 elementos. –

Cuestiones relacionadas