I take some quibble with what the author presents as the “naive solution” - I would have done something like <textarea oninput="event.target.nextElementSibling.textContent = event.target. value.length;"></textarea><span></span> for this - but the general principle of queuing up changes and only processing once is very good.
In my desktop gui library, I used to have it automatically recalculate layout when any widget is added to the tree. After someone complained about bad performance in a loop, I changed it to something very similar here - on next idle loop, recalculate if needed. Now the loop is fine. But on the other hand, if you ask for width after adding something but before it recalculates, you will get an invalid thing. I suppose I could make that a property getter that forces eager eval as well. But meh still I’m a LOT happier with it this way and 99% of the time, all users see is the better performance.
Yeah, and it’s a performance cliff. You may have a fast DOM modification loop, add one new widget that happens to query styles, and suddenly performance tanks.
It’s especially painful when you build your UI out of components. The abstraction barrier makes it basically impossible to coordinate DOM access across components, and you may easily end up with lots of interleaved DOM reads and writes.
In one app I’ve worked on we’ve had to redesign the whole component architecture and tear components apart to let them schedule DOM reads and writes, so instead or WRWRWRW loops, we could have a global scheduler to turn it into WWWWRRRR.
I take some quibble with what the author presents as the “naive solution” - I would have done something like
<textarea oninput="event.target.nextElementSibling.textContent = event.target. value.length;"></textarea><span></span>
for this - but the general principle of queuing up changes and only processing once is very good.In my desktop gui library, I used to have it automatically recalculate layout when any widget is added to the tree. After someone complained about bad performance in a loop, I changed it to something very similar here - on next idle loop, recalculate if needed. Now the loop is fine. But on the other hand, if you ask for width after adding something but before it recalculates, you will get an invalid thing. I suppose I could make that a property getter that forces eager eval as well. But meh still I’m a LOT happier with it this way and 99% of the time, all users see is the better performance.
That eager getter is kind of like style recalculations on property access in DOM API, btw. :)
Yeah, and it’s a performance cliff. You may have a fast DOM modification loop, add one new widget that happens to query styles, and suddenly performance tanks.
It’s especially painful when you build your UI out of components. The abstraction barrier makes it basically impossible to coordinate DOM access across components, and you may easily end up with lots of interleaved DOM reads and writes.
In one app I’ve worked on we’ve had to redesign the whole component architecture and tear components apart to let them schedule DOM reads and writes, so instead or WRWRWRW loops, we could have a global scheduler to turn it into WWWWRRRR.