Currently elements that need to be retrieved at runtime (for events and bindings) are given a identifier at compile time. Subsequent code gen uses that identifier for building expressions that refer to that element. The identifier starts with p and then several random characters (identifiers are checked across components not to collide although it is not guaranteed across foreign components). For example the following button will get a class with something like p1234:
After analysis the button will become something like <button class="p1234">..</button>
This is so that during hydration adding the event listener is as simple as this.querySelector(".p1234").addEventListener(..) or during runtime if the value of someText is altered then this.querySelector(".p1234").innerText = ... There is also a Map on the component instance which caches them so repeated accesses don't go looking for elements again. This abstraction is through the method Component.getElem
This was a simple early implementation in Prism but there are some issues with this:
Additional payload during server side rendering for all the class names.
querySelector performance concerns for large trees
Issues around elements non unique elements in for loops
Caching is mem expensive and sometimes unnecessary. Map is not created lazily
A solution:
Instead of adding identifiers and generating lookups via identifiers, elements could be retrieved through getting their index in the tree.
Currently elements that need to be retrieved at runtime (for events and bindings) are given a identifier at compile time. Subsequent code gen uses that identifier for building expressions that refer to that element. The identifier starts with
p
and then several random characters (identifiers are checked across components not to collide although it is not guaranteed across foreign components). For example the followingbutton
will get a class with something likep1234
:After analysis the button will become something like
<button class="p1234">..</button>
This is so that during hydration adding the event listener is as simple as
this.querySelector(".p1234").addEventListener(..)
or during runtime if the value ofsomeText
is altered thenthis.querySelector(".p1234").innerText = ..
. There is also aMap
on the component instance which caches them so repeated accesses don't go looking for elements again. This abstraction is through the methodComponent.getElem
This was a simple early implementation in Prism but there are some issues with this:
querySelector
performance concerns for large treesMap
is not created lazilyA solution:
Instead of adding identifiers and generating lookups via identifiers, elements could be retrieved through getting their index in the tree.
Get element by index:
The indexes can be calculated at build time. This is already the process for referencing elements in for loops.
Things to consider:
getElement(0, 0, 0)
could abstract across the repeated.children[x]
chaininggetElement(0, currentIndex, 0)
children
vschildNodes
as the former doesn't take into account text nodeschildren
getter to components with slots as identifiers are used