WebComponent
The WebComponent
class is one of the main classes you need to interact with in order to create your components.
That alone make things pretty simple to learn.
This component by default extends the HTMLElement class which means it that there is no support to extend specific HTML element.
So instead of initializing your components like this:
class MyButton extends HTMLElement {
// code goes here
}
... you will do this:
class MyButton extends WebComponent {
// code goes here
}
Registration
The WebComponent
class also takes care of registering the component for you by exposing the static register
method that you can call to let the document know you have a custom component to use.
class MyButton extends WebComponent {
// code goes here
}
// registers a "my-button" tag
MyButton.register();
You may also register multiple components at once using the static registerAll
method.
class MyButton extends WebComponent {}
class FlatList extends WebComponent {}
class SiteMenu extends WebComponent {}
WebComponent.registerAll([
MyButton, // registers a "my-button" tag
FlatList, // registers a "flat-list" tag
SiteMenu, // registers a "site-menu" tag
])
Component Naming
By default, the WebComponent
uses the class name to change into an HTML tag name.
Using the MyButton
example, it will use the class name to create the my-button
tag and register it like that.
You may also specify your own name using the register
call or the static tagName
property inside the class;
class MyButton extends WebComponent {
// do this
static tagName: 'special-button'
}
// or this
MyButton.register('special-button');
Note: The register call will override the "tagName" property as it is more specific.
It is also important to make sure that both, class name or tag name, needs to be at least two words to be considered a valid tag name. This is actually a native component name convention.
The following are considered invalid names:
- Counter or counter
- Widget or widget
- Field or field
- Title or title
You can compose the name or prefix with something like:
- BFSCounter or bfs-counter
- VideoWidget or video-widget
- InputField or input-field
- SmallTitle or small-title
Learn About WHATWG Valid Component Naming Spec
Initialization
The WebComponent
also takes care of attaching shadow root and all the setup needed to prepare
your component for rendering.
class CountDisplay extends WebComponent {
static observedAttributes = [
'count'
];
get template() {
return '{count}'
}
}
CountDisplay.register();
// to create an element from the component do this
const countDisplay = new CountDisplay();
// or this
const countDisplay = document.createElement(CountDisplay.tagName);
// you can access public properties and methods of the component
countDisplay.count = 100;
document.body.appendChild(countDisplay);
/* will render
<count-display>
#shadow-root (open)
"100"
</count-display>
*/
Learn More about Observed Attributes
When your component is about to render, the template is processed. This is the only time your template is used and any updates after that happens directly on the DOM.
Shadow DOM
By default, the WebComponent
will render your component content inside an open
shadow-root.
You can change that by specifying the mode
static property inside the class.
class MyButton extends WebComponent {
static mode: 'closed'
}
In case you don't want the shadow root, you can just set it to none
;
class MyButton extends WebComponent {
// will not attach shadow root to component
static mode: 'none';
}
Note: The none
mode is not natively supported. It is a unique mode specific to this library.
The shadow-root element is accessible via the root
or shadowRoot
property. It will be null
if the mode is closed
or the component element itself if the mode is none
.
class MyButton extends WebComponent {
onMount() {
console.log(this.root);
console.log(this.shadowRoot);
}
}
parseHTML
The HTML string used by this framework will not be parsed correctly by the browser as it allows many "illegal" symbols mixed with HTML in the body or attribute values.
Because of this, you should always try to parse HTML string specific
to this library using the WebComponent.parseHTML
static method as it takes in consideration all the special syntax.
const html = `
<my-button>
<span>Hello</span>
</my-button>`;
// parseHTML returns a DocumentFragment containing the parsed HTML nodes
// it is not a fucntioning component, just its DOM representation
const myButton = WebComponent.parseHTML(html).children[0];
The parseHTML
will not create a component from the string provided. It will return
a DocumentFragment containing all the elements matching the string template you provide.
This method will be particularly useful when you are creating complex custom directives
forceUpdate
The forceUpdate
method is used internally to update the component content. It is a NOT recommended way to update your component.
You should NEVER feel the need to use this method as the component does its job to update the DOM when there is change at any level of the properties value.
Also, it will not cause the onUpdate livecycle method to be called. Try your best to trigger updates via property and attribute changes.