3 ms·
We all know that Element.innerHtml = "..." can be significantly faster than set of individual DOM mutating calls. Element.innerHtml = ... gets executed as singl
by c-smile 10y ago
We all know that Element.innerHtml = "..." can be significantly faster than set of individual DOM mutating calls. Element.innerHtml = ... gets executed as single transaction - relayout happens only once, at the end of it. Yet there is no overhead on JS-native bridging and function calls in JS in general.
But the need of "transactioned" DOM updates is not just about the speed. There are other cases when you need this. In particular:
1. Massive DOM updates (that's your case), can be done with something like: Element.update( function mutator(ctx) ). While executing the mutator callback Element.update() locks/delays any screen/layout updates.
2. That Element.update( function mutator(ctx) ) can be used with enhanced transitions. Consider something like transition: blend linear 400ms; in CSS.
While executing the update browser makes snapshots of initial and final DOM states and does blending of these two states captured into bitmaps.
3. transactioned update of contenteditable. In this case Element.update() groups all changes made by the mutator into single undoable operation. This is a big deal actually in WYSIWYG online editors.
There are other cases of course, but these three functionalities are what I've implemented in my Sciter Engine ( http://sciter.com http://sciter.com ) already - proven to be useful.
- dionidium 10y ago"We all know that Element.innerHtml = "..." can be significantly faster than set of individual DOM mutating calls" Not necessarily: http://stackoverflow.com/questions/8461851/what-is-better-appending-new-elements-via-dom-functions-or-appending-strings-w/8461877#8461877 http://stackoverflow.com/questions/8461851/what-is-better-ap... That's an old post, but even then the conventional wisdom didn't hold up.
- c-smile 10y ago"Not necessarily". Of course there are situations when these two methods of DOM update are on par. But in any case I agree with one of answers there: "If you don't mind the fact that innerHTML is a bit limiting (only total replacement of DOM sub-tree rooted at target element) and you don't risk a vulnerability through injecting user-supplied content, use that. Otherwise, go with DOM." When you do for example this: element.setAttribute("a","b"); browser 1. drops all resolved CSS rules on element, its siblings, its parent and all children. Just in case you have CSS rules like: element[a="b"] > span { display:none } 2 Invalidates rendering tree of the element's parent. And when you do element.appendNode(node): it does the same as above + plus ensures consistency of HTML DOM (<select> cannot contain <div>s for example). If you have multiple calls like these then all steps above need to be done for each of them. Engines can optimize such cases but not that much in some cases. While browser do element.innerHtml it does each step strictly once: build consistent DOM, resolve styles, build rendering tree and mark window [area] as needed painting - request painting.
- TabAtkins 10y ago> drops all resolved CSS rules on element, its siblings, its parent and all children. Browsers optimize this, too - they try hard to keep up metadata structures that tell them whether they need to invalidate styling or not. (This is why mutating the stylesheet is so expensive - browsers have to freshly rebuild the supporting data structures. They could optimize that too, but it's a lot of effort for a rare case.) So if there's no rules mentioning an [a] attribute in the page, el.setAttribute("a", ...) will generally not do anything. (One of the benefits of shadow DOM is that the shadow trees are scoped away from the main tree and each other, so you can have more expensive rules in them without making the rest of the page slow. Yay for componentization!)
- c-smile 10y ago"So if there's no rules mentioning an [a] attribute in the page, el.setAttribute("a", ...) will generally not do anything." That's true in general but there are exceptions as usual. Changing @href may trigger not only [href] rules but also :link ones. And :link rules are always present at least in default style sheet. @value triggers :empty. And so on. But if someone in some library in galaxy far far away (small library used by your application) will add that [a] rule then magically you will get a spike on innocuous el.setAttribute("a", ...) calls in your code. That's one of points of having transactional yet explicit DOM update mechanism. We have jQuery, Angulars, React, Ember, Vue, (you name it) that definitely need such thing. Sites/webapps that do not use one of those are quite rare these days.
- deleted 10y ago[deleted]
- jerf 10y agoSeems to me that page supports the claim that .innerHTML can be faster than individual DOM mutating calls.