2010-01-29 5 views
6

Siendo interesado en construir html chunks off-dom antes de insertarlos en el dom, he hecho algunas pruebas usando dynatrace. Utilicé el método de Bobince: Is there any way to find an element in a documentFragment?getElementById basado en contexto es 1000 veces más lento que getElementById nativo. ¿Los motores de selección como chisporroteo utilizan una estrategia más inteligente?

Me pareció casi 1000 veces más lento (en IE7), lo que me sorprendió mucho.

Dado que la función es bastante básica, me preguntaba acerca de la estrategia utilizada por motores como chisporroteo.

Me gustaría saber si hay formas más eficientes de seleccionar los nodos según el contexto.

+0

No debería sorprenderlo. Inmediatamente después del código, explícitamente sugiere no usarlo: "Seguramente sería mejor seguir las referencias a medida que avanzas que confiar en una función ingenua y de bajo rendimiento como la anterior". –

+0

la sorpresa fue que el orden o magnitud: 1000. Esperaba algo entre 2 y 100. – Olivvv

Respuesta

1

Los motores de selector de marco generalmente se evalúan con la mano derecha, por lo que esperaría un selector de ID contextual a document.getElementById la ID y luego verificar si los resultados estaban en el nodo de contexto incrementando el parentNode s. Esto es razonablemente rápido, pero no funcionará para árboles DOM fuera del documento como en este ejemplo. Los motores de selección tendrían que hacerlo de forma desesperadamente lenta, o no les importa (por ejemplo, Sizzle no funciona con DocumentFragment).

Hay una forma mejor de obtener la ID dentro de un fragmento que he recordado desde entonces, para los navegadores que implementan Selectors-API (IE8, Firefox 3.5, Opera 10, Safari 3.1, Chrome 3). Puede utilizar querySelector aplicar un selector CSS con el DocumentFragment como un nodo de contexto, ya que la API requiere DocumentFragment implementos NodeSelector:

alert(frag.querySelector('#myId')) 

Esto no es tan rápido como getElementById, pero es muchísimo mejor que la versión DOM .

Desafortunadamente la mayoría de los marcos que tienen optimizaciones Selectores-API no las van a utilizar en este caso o cualquier otro con nodos de contexto, porque la forma en que funciona el nodo de contexto es diferente en querySelector [All] a cómo los marcos implementados tradicionalmente, haciéndolos incompatibles.

Selectors-API Level 2 propone métodos de 'ámbito' que se comportan como los selectores de marcos tradicionales ... pasará un tiempo antes de que se pueda usar, pero probablemente no veremos selectores contextuales optimizados en los marcos existentes hasta entonces. Creo que es una lástima, ya que aunque el método querySelector de usar el nodo de contexto para el filtrado pero no el alcance no es tan bueno, todavía es bastante útil para todos los casos comunes.

+1

¿Estás seguro de 'Element.getElementById'? La premisa completa de la selección contextual por ID es incorrecta en mi humilde opinión. Una identificación es única en un contexto de "documento", no en un "elemento" o "fragmento de documento". –

+0

Oh sí. Parece que estoy mintiendo y pensando en getElementsByTagName. Oops! Actualizando ...He encontrado algunas cosas más para jugar :-) – bobince

+0

Ah. Me sorprendió que pudiera haberme perdido algo como Element.getElementById(). Leí algunas cosas sobre querySelector, pero tengo que centrarme en IE7. @Chetan el punto es realizar la selección en html que aún no está en dom. – Olivvv

0

Si no te importa la inserción de su DocumentFragment en DOM temporalmente ...

function getElementFromFragById(frag, id) { 
    var tempDiv = document.createElement("div"); 
    tempDiv.style.display = "none"; 
    tempDiv.appendChild(frag); 
    document.body.appendChild(tempDiv); 
    var elem = document.getElementById(id); 
    document.body.removeChild(tempDiv); 
    return document.getElementById(id) ? null : elem; //if the element still exists, we have a problem 
} 

Esto funciona de forma fiable el tiempo que su documentFragment no contiene elementos con el ID que ya existen en document y desea buscar en esa identificación.

+0

Quiero manipular html off dom esencialmente para evitar reflows, que son un gran costo de rendimiento. Desafortunadamente IE7 se vuelve a filtrar cuando los elementos ocultos se ven afectados. Ver http://www.phpied.com/the-new-game-show-will-it-reflow/ En una nota lateral, no estoy seguro de si el fragmento todavía es un fragmento cuando revise su función, por lo que probablemente se cancelaría el rendimiento se gana al usar un fragmento. De todos modos, estoy interesado en operaciones fuera de dom, así que no necesariamente fragmentos. – Olivvv

Cuestiones relacionadas