Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

create/append node vs innerHTML

Does anyone have a good reason to use one over the other? As far as I can tell, create/append node simply prevents you from creating invalid code, while innerHTML allows you to inject multiple nodes at once.

Given that I need to insert several tags, it seems to make sense to use innerHTML. Does anyone have a different take?

like image 287
Matrym Avatar asked Nov 07 '09 20:11

Matrym


2 Answers

This is always a contentious argument, partially because the origin of innerHTML being somewhat dubious from a standards perspective. I think the QuirksMode article is still relevant, but I'd love to see it updated. Perhaps contact ppk about updating them, though I'm sure he's busy. We could all benefit from performance testing the assumptions we make in web development. In the end claims require hard data to prove, otherwise it's really just talk.

Anyway, I did some searching and found some interesting articles relevant to this discussion. I don't remember hearing of DocumentFragments before, they're real interesting.

  • DOM DocumentFragments
  • jQuery Performance Rules
  • Improve your jQuery - 25 excellent tips
  • Speed test: innerHTML versus DOM manipulation ... a test that actually tests the speed, worth it for anyone who wants to collect some current data on browsers
like image 185
artlung Avatar answered Sep 23 '22 13:09

artlung


Given that I need to insert several tags, it seems to make sense to use innerHTML.

Only ‘several’? Then speed is not an issue. It's when you're creating a hundred you have to think about what you're doing. It's not really the creating that's the problem, it's the child node list manipulation that gets slower and slower as you add each extra element.

As for appending, you don't really have any choice. You can't set the innerHTML without losing the existing content, so unless you're happy with serialising and re-parsing that (which wipes out any non-serialisable data like form contents, JavaScript properties/references and event handlers) you end up setting the innerHTML of another element and moving each child over one by one. This is what many frameworks do and it typically ends up even slower than manual create-and-appendChild.

Depending on your situation (specifically: how many child nodes are already in the target element, and how many are you going to add?) it can be faster to break down the operation into smaller manipulations on a DocumentFragment, whose children can be appended to an element's children all in one go instead of one-by-one. This is much faster. Unfortunately, it is not possible to set innerHTML on a DocumentFragment.

There may also be faster hacks using Range objects to move a load of HTML at once, but unfortunately Ranges are highly cross-browser variable. It seems to me, though, that someone ought to be able to build a fast append-html out of IE's range.pasteHTML and W3's range.extractContents. Anyone up for it?

As far as I can tell, create/append node simply prevents you from creating invalid code

Potentially invalid markup doesn't just mean your application breaks in some browsers. When you're blindly splicing together HTML without escaping like an idiot:

element.innerHTML= '<a href="'+url+'">'+title+'</a>';

then you have a client-side cross-site-scripting security hole that is just as bad as a server-side one.

You can, of course, compromise, by creating the elements and setting their contents in separate steps. For example:

element.innerHTML= '<table>'+'<tr><td>X</td><td><a href="#">go</a></td></tr>'.repeated(urls.length)+'</table>';
for (var i= 0; i<urls.length; i++) {
    var row= element.firstChild.rows[i];
    row.cells[0].firstChild.data= urls[i];
    row.cells[1].firstChild.href= urls[i];
}

(string.repeated is not standard JavaScript, but its use here is obvious.)

like image 28
bobince Avatar answered Sep 26 '22 13:09

bobince