Being interested in building html chunks off-dom before to insert them in the dom, I have done some testing using dynatrace. I used b开发者_开发问答obince's method : Is there any way to find an element in a documentFragment?
I found it to be almost 1000 time slower (in IE7), which surprised me a lot.
Since the function is pretty basic, I was wondering about the strategy used by engines such as sizzle.
I would like to know if there is some more efficient ways to do context-based node selection ?
Framework selector engines are generally evaluated right-hand-first, so I would expect a contextual ID selector to document.getElementById
the ID and then check to see whether the results were in the context node by stepping up the parentNode
s. This is reasonably fast, but it won't work for out-of-Document DOM trees like this example. Selector engines then would have to do it the desperately slow way, or not care (eg. Sizzle doesn't work with DocumentFragment
).
There is a better way of getting the ID inside a fragment I've remembered since then, for browsers that implement Selectors-API (IE8, Firefox 3.5, Opera 10, Safari 3.1, Chrome 3). You can use querySelector
to apply a CSS selector with the DocumentFragment
as a context node, as the API requires DocumentFragment
implements NodeSelector
:
alert(frag.querySelector('#myId'))
This isn't quite as fast as getElementById
, but it's loads better than the DOM version.
Unfortunately most frameworks that have Selectors-API optimisations won't use them in this case or any others with context nodes, because the way the context node works is different in querySelector
[All
] to how the frameworks traditionally implemented it, making them incompatible.
Selectors-API Level 2 proposes ‘scoped’ methods that behave like the traditional framework selectors... it'll be a while before that's usable, but we probably won't see optimised contextual selectors in the existing frameworks until then. I think this is a shame, as although the querySelector
method of using the context node for filtering but not scoping is not quite as good, it's still pretty much usable for all the common cases.
If you don't mind inserting your documentFragment into DOM temporarily...
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
}
This works reliably as long as your documentFragment
doesn't contain elements with id that already exist in document
and you want to search on that id.
精彩评论