@twobirds/microcomponents
v0.1.20
Published
Micro Components Organization Class
Downloads
232
Maintainers
Readme
MICRO COMPONENTS
MCs are function blocks that you attach to DOM nodes. These are re-usable in any framework, and you can have any number of MCs in one DOM node.
There are helpers for the following functionalities:
- Web Components: create native web components. Their functionality is comprised of a set of inner MCs.
- State is done by observable objects that you can attach callbacks to. This also allows for 1-way binding to DOM placeholders, and it can be extended to allow for complex data driven state machines.
- Form Handling allows for 2-way binding from an observable form object to DOM form input elements.
- Communication between DOM micro components is ensured via direct selected or directional bubbling CustomEvent's.
- Autoloading allows for build-free websites that dynamically load JS requirements into DOM HTMLElements.
The distinguishing feature - compared to other frameworks - is its minimalism, portability and granular modularization. In an almost literal sense MCs work like childrens building blocks, where a chest full of unassuming parts lets you compose whatever functionality lies in your imagination.
You work with one of the established frameworks? You can still put this hands-on tool in your tool belt. You then have a plugin fallback solution for when your FW fails you or lacks functionality.
Status
For a quick glance try this...
In manual testing ( also a speed test).
Check the typedoc API reference if you want to drill into the source code.
The progress of coding is being streamed on twitch and youtube.
Simple Usage Examples
Micro Components
Hint: This code only shows how Micro Components are stored in the DOM.
before:
<div></div>code:
// create a custom micro component class
class MyMC extends DC{
constructor( target ){
super( target );
}
helloWorld(){
console.log( 'Hello World' );
}
}
// get some element from the DOM
const element = document.querySelector('div');
// Add the custom micro component instance to the target element
DC.add(
element,
'myMC',
new MyMC( element )
);
// Hello World
element
._mc
.myMC
.helloWorld();after:
<div data-mc></div>The data-mc attribute indicates that this HTML element contains at least one micro component. This is needed for the selectors.
The _mc property is the only interference with the DOM, so any other system should be happy to work with this.
Web Components / Custom Elements
code:
// create a custom micro component class
class MyComponent extends DC{
constructor( target ){
super( target );
}
// this event handler is attached automatically
onClick(){
console.log( '<my-component> clicked!' );
}
}
defineCE( 'my-component', MyComponent );after: you can use ...
<my-component></my-component>... in your template.
Or you can construct it programmatically:
const myComponentClass = getCE('my-component');
const body = document.body;
body.append( new myComponentClass() );State and 1-way-binding
code:
// create a custom micro component class
class MyMC extends DC{
constructor( target ){
super( target );
this.state = { text: 'Hello world!' };
// observe one property ...
observe( this, 'state' );
// or observe all properties defined so far
observe( this );
this.target.innerHTML = '{text}';
// one way binding
this.state.bind( target ); // links the state to DOM placeholders
// attach your own callbacks
this.state.observe( (value) => {
console.log(value);
});
// now simply changing the state will change the DOM
this.state.text = 'Hallo Welt';
}
}Forms and 2-way-binding
code:
// create a custom micro component class
class MyMC extends DC{
constructor( target ){
super( target );
this.form = { textinput: 'Hello world!' };
this.target.innerHTML = '<input name="textinput" />';
// link the form property to the DOM input fields
formValues( this, 'form', this.target );
// now simply changing the form property will change the DOM input fields
this.form.textinput = 'Hallo Welt';
}
}Event Handlers
Native Events
code:
// create a custom micro component class
class MyMC extends DC{
constructor( target ){
super( target );
// attach event handlers programatically
const onClickHandler = this.on( 'click', () => {
// ...
});
this.one( 'click', () => {
// ...
});
this.off( 'click', onClickHandler );
}
// this event handler is attached automatically
onClick(){
console.log( 'HTMLElement clicked!' );
}
// this event handler is attached automatically
oneClick(){
console.log( 'HTMLElement clicked! ( only fires once )' );
}
}Custom Events
code:
// create a custom micro component class
class MyMC extends DC{
constructor( target ){
super( target );
payload = {
test: 42
};
setTimeout( () => {
this.trigger('customEvent', payload );
});
}
// this event handler is attached automatically
onCustomEvent( ev ){
console.log( 'onCustomEvent called with', ev.data.test ); // "42"
}
}Goal
This code aims at improving Javascript modularity and encapsulation. Micro Components are built on OOP for structure, so you should embrace DRY, KISS and SOLID principles.
MCs provide a runtime app structure that is directly linked to the browser DOM. That is you don't need web components, you can attach MCs to plain HTMLElements. Having said this: the library also allows for standard web component programming, acting as a framework.
In general this is a HTML / Web Standards first system. There is almost no abstraction, especially not for templating, except state binding to the DOM via simple placeholders.
It has no interference with other frameworks, since it creates a second layer that hovers above the DOM. So what you intended to work as an add-on to React, is usable e.g. in Angular also.
And, of course, you can use it as your main framework using its custom web component functionality.
Its basic principle is composition over inheritance. Also it helps to embrace DIY (Do It Yourself) over Toolchains, but this is up to your personal preference.
You can use Vanilla JS or Typescript or both in parallel in your project. For example you could use plain JS for rapid prototyping functionalities, then convert to TS for production.
Most of all this system by design allows for outsourcing without sharing the main development system. It is absolutely granular as it enforces DRY (Don't Repeat Yourself).
Finally it allows for a clear distinction between Junior, Senior and Architect roles in a project. No more hiring junior programmers with 5 years experience in 50 tools under their belt. A junior in this system is somebody who likes HTML, CSS and JS/TS - nothing more. Teaching all of this system starting at zero takes 1 day. The rest is finger muscle memory and learning/knowing web standards.
Documentation
This repository exports 4 independent functionalities:
Micro Components contains the MC and DC classes you can use as super classes.
Elements lets you define and use your own native web components. Uses (1).
- Observables add observability and run time type safety to object properties. Also they provide 1-way binding to placeholders in your template HTML.
- Formvalues gives you 2-way binding between a HTML form and an observable object. Uses (3).
Also there is a bundle file that contains all of the above.
To see what can be done, go to additional concepts which shows what it already has been used for.
Distinguishing Features
There are a few potentially unique aspects of this micro components system that might differentiate it from other framework or library:
Pure OOP Approach: The system explicitly positions itself as a strict object-oriented alternative to the functional approaches that dominate many modern frameworks.
Minimal Interference: The system has minimal DOM interference, only adding _mc property to DOM nodes that contain code. This makes it unusually compatible with other frameworks or libraries.
Hierarchical Component Traversal: The built-in ancestor/closest/child/descendant traversal methods provide a clean way to navigate component relationships.
Direct DOM Integration: Unlike virtual DOM-based frameworks, this approach works directly with the actual DOM while still providing component encapsulation.
Outsourcing Potential: Your external coders do not need to access your code repository or your toolchain.
The strongest argument might be for developers who prefer OOP, want minimal framework lock-in, and need a lightweight solution that works well with existing code or other libraries.
Contact
Feel free to contact me for any questions or inquiries:
email Frank Thürigen
You can fund this.
Disclaimer
I decided to extract this functionality from the twoBirds framework, because it is a useful tool in itself and it is framework agnostic. It relies solely on the standard DOM and native javascript or typescript.
Later this will be backported into twoBirds as a dependency, and twoBirds will become completely modularized on the base of MCs.
This is a massive undertaking. MCs are just the foundation of what I do. I am about to dump 20+ years of javascript programming into open source libraries, so feel free to fund this. The better this is funded, the faster it will be done. Given enough resources, I will start a crowdfunded company that will develop a new open source ecosystem for javascript/typescript programming.
