prism icon indicating copy to clipboard operation
prism copied to clipboard

Element retrieval using indexes rather than identifiers

Open kaleidawave opened this issue 3 years ago • 0 comments

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 vs childNodes 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

kaleidawave avatar Mar 20 '21 18:03 kaleidawave