Javascript DOM batch add/remove/edit elements & children with only 2 DOM calls
Some background to understand how it works
I have a hierarchy of Javascript Objects, in this case I will call them Sprites. Each Sprite reference 1:1 an HTML Element.
This is an abstraction layer for HTML & CSS;
Currently when you change a property:
mySprite.set('width', 100);
it will not update the HTML Element in a synchronous way, but will start a timer of milliseconds, in order to wait for other changes applied to this HTML Element.
Ex.:
mySpite.set('width', 100);
after this change, the sprite is invalidated and after 25 milliseconds will update the HTML Element
mySprite.set('height', 100);
now this will restart the timer of 25 milliseconds and will wait 25 milliseconds to update the DOM with the width & height at the same time instead of 2 DOM changes
The problem
Now the problem I'm facing is this: (Hierarchy below represents the Sprites hierarchy, let's call them by the name they have)
I have this hierarchy and imagine that Sprites "aaaba" and "aaabc" changes it's style. Then the Sprite "aaab" adds more 3 Sprite children (they are shown in parenthesis, "aaabd", "aaabe" and "aaabf").
or in steps:
- aaaba.set('width', 100);
- aaabc.set('height', 45);
- aaab.addChildren(...3 children...);
Until now I would not want to make any updates to the DOM. After all Sprites have changed their properties and added and removed other Sprites (HOW DO I DISCOVER THIS MOMENT? with another timer of 25milliseconds?), I would want to work like this:
- Remove the Elements from DOM that are about to make major changes: aaa.removeChild(aaab)
- Change the style, and as they are not on DOM because their parent was removed in step1 this will not be so costly: aaaba.style.cssText = aaabc.style.cssText = "my new css"
- Append the children to the "aaab" element
- Append again the "aaab" to "aaa": aaa.appendChild(aaab);
In th开发者_JAVA百科is way is faster to make DOM changes.
a
|-aa
| |-aaa
| | |-aaaa
| | |-aaab<
| | | |-aaaba<
| | | |-aaabb
| | | |-aaabc<
| | | |-(aaabd)<
| | | |-(aaabe)<
| | | |-(aaabf)<
| | |-aaac
| | |-aaad
| |-aab
| | |-aaba
| | |-aabb
| |-aac
|-ab
| |-aba
| |-abb
|-ac
|-aca
|-acb
I suppose there is no need to remove something from element tree, which is not part of a document.
Here is algorithm (I know nothing about your object model, so I made everything up)
function applyChanges (sprite, detached) {
var detach = false, container
if (!detached) {
for (var i = 0; i < sprite.childSprites.length; i++) {
if (areChangesMajor(sprite.childSprites[i])) {
detach = true
break
}
}
}
if (detach) {
container = sprite.element.parentNode
container.removeChild(sprite.element)
detached = true
}
// ...
// your stuff (applying styles, adding child sprites, etc) should be there
// ...
for (var i = 0; i < sprite.childSprites.length; i++) {
applyChanges(sprite.childSprites[i], detached)
}
if (detach) {
container.appendChild(sprite.element)
}
}
精彩评论