prism
prism copied to clipboard
Element retrieval using indexes rather than identifiers
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
:
<template>
<button @click="alert">{someText}</button>
</template>
..
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.
<template>
<div>
<div>
<button @click="alert">{someText}</button>
</div>
</div>
</template>
Get element by index:
const button = this.children[0].children[0].children[0]
The indexes can be calculated at build time. This is already the process for referencing elements in for loops.
Things to consider:
- Adding something like
getElement(0, 0, 0)
could abstract across the repeated.children[x]
chaining - For elements in loops rather than a static number it would be a variable e.g.
getElement(0, currentIndex, 0)
-
children
vschildNodes
as the former doesn't take into account text nodes - Compare performance
- Is element caching necessary?
- Fragments don't exist and "for"s are done under single elements so elements indexes should be reasonably fixed
- Adding a
children
getter to components with slots as identifiers are used