Web components aka extending HTML with custom tags with structure, styling and behavior defined in JavaScript is a great idea (though arguably an obvious one that should've been available from the start) but with a horrible implementation. Here's why:
you can't create child elements in the constructor while the DOM is loading, so good luck initializing components declared in HTML. You're going to have to query the document for components and initialize them on DOMContentLoaded.
disconnectedCallback() is called asynchronously (probably on GC) so you can end up with two component instances with the same id at the same time. Good luck implementing something that binds a component to another automatically by id whenever the target component is attached to the DOM.
connectedCallback() is called before children are created (and even before they are parsed), instead of going depth-first after they are created. Good luck trying to set up the children automatically when the component is attached.
shadow DOM/CSS makes components unstylable by library users but at least you're not forced to use it.
A component API that's much more useful can be easily implemented (albeit somewhat inefficiently) by overriding all built-in DOM creation and manipulation API methods so that they scan all attached and detached elements in order to create components, and have them receive attach/detach events. And as a bonus, this API also lets you register an attach/detach handler for any selector including for built-in tags, not only your registered component tags.
This was implemented in divs.js (need to read glue.js as well to understand it). The whole "web components" thing is implemented in:
bind_component, the analog to CustomElementRegistry.define()
init_component and init_child_components which are called whenever DOM trees are created.
bind and bind_children which are called whenever DOM trees are attached/detached to/from DOM.
This implementation doesn't actually override the native DOM manipulation APIs simply because I don't use them (I use my own wrappers that are safer and more convenient), but it totally could, and that would make components available to third-party libraries that create/attach DOM elements.
Web components aka extending HTML with custom tags with structure, styling and behavior defined in JavaScript is a great idea (though arguably an obvious one that should've been available from the start) but with a horrible implementation. Here's why:
you can't create child elements in the constructor while the DOM is loading, so good luck initializing components declared in HTML. You're going to have to query the document for components and initialize them on DOMContentLoaded.
disconnectedCallback() is called asynchronously (probably on GC) so you can end up with two component instances with the same id at the same time. Good luck implementing something that binds a component to another automatically by id whenever the target component is attached to the DOM.
connectedCallback() is called before children are created (and even before they are parsed), instead of going depth-first after they are created. Good luck trying to set up the children automatically when the component is attached.
shadow DOM/CSS makes components unstylable by library users but at least you're not forced to use it.
(reddit thread)
An alternative
A component API that's much more useful can be easily implemented (albeit somewhat inefficiently) by overriding all built-in DOM creation and manipulation API methods so that they scan all attached and detached elements in order to create components, and have them receive attach/detach events. And as a bonus, this API also lets you register an attach/detach handler for any selector including for built-in tags, not only your registered component tags.
This was implemented in divs.js (need to read glue.js as well to understand it). The whole "web components" thing is implemented in:
bind_component
, the analog toCustomElementRegistry.define()
init_component
andinit_child_components
which are called whenever DOM trees are created.bind
andbind_children
which are called whenever DOM trees are attached/detached to/from DOM.This implementation doesn't actually override the native DOM manipulation APIs simply because I don't use them (I use my own wrappers that are safer and more convenient), but it totally could, and that would make components available to third-party libraries that create/attach DOM elements.