Open LePhenix47 opened 1 year ago
Web Components have a lifecycle, and there are several methods that can be implemented to customize their behavior:
constructor()
: Method that is called when an instance of the element is created or upgraded. It must include a super()
call to inherit the methods of HTMLElement. The constructor()
method is generally used to attach the web component to the shadow root and set its content
ex:
constructor() {
super();
//We create the cotnainer that holds the web component
const shadowRoot: ShadowRoot = this.attachShadow({ mode: "open" });
//We clone the template
const clonedTemplate: Node = templateElement.content.cloneNode(true);
//We add it as a child of our web component
shadowRoot.appendChild(clonedTemplate);
}
observedAttributes()
: Static method used to store the array of all the custom attributes of the component
ex:
static get observedAttributes() {
//We indicate the list of attributes that the custom element wants to observe for changes.
return ["age"];
}
connectedCallback()
: Method called every time the element is inserted into the DOM
It can be used to attach event listeners or initialize other elements
ex:
connectedCallback() {
const container = this.shadowRoot.querySelector(".container");
container?.addEventListener("load", (e)=>…);
}
disconnectedCallback()
: Method called every time the element is removed from the DOM
It can be used to remove event listeners or clean up other elements
ex:
disconnectedCallback() {
const container = this.shadowRoot.querySelector(".container");
container?.removeEventListener((e)=>…);
}
attributeChangedCallback(name, oldValue, newValue)
: Method called by the browser's web API when an observed attribute of a custom element is added, removed, or changed. It can be used with a switch-case
statement to change the component depending on the attribute value that changed
ex:
attributeChangedCallback(name, oldValue, newValue){
switch(name){
case "age":{
//…
break;
}
default: break;
}
}
set
and get
:
Setters and getters are used to define properties on a web component. They allow you to customize the behavior of the component when a property is accessed or modified.To create a getter or setter, you can use the get and set keywords followed by the name of the property:
class MyComponent extends HTMLElement {
set age(newAge) {
this.setAttribute("age", newAge);
}
get age() {
return this.getAttribute("age");
}
// other lifecycle methods
}
In a Web Component, when we set a new value for a setter, we can update the attribute values of the component. This is because the set function of a setter can be used to update the corresponding attribute value using the setAttribute()
method
With that we can get the value:
const currentAge = this.age
and set a new value:
this.age = 20
⚠ Warning: Each method has its own purpose in the Web Component lifecycle, and it's important to use them correctly to ensure proper behavior and avoid memory leaks.
Web Components use Shadow DOM to encapsulate their styles from the main DOM, allowing them to be reusable across different parts of a web page or application. Shadow DOM provides a set of CSS pseudo-classes that allow you to target specific parts of a Web Component's shadow tree.
Here are some of the most commonly used CSS pseudo-classes for Web Component styling:
:host
: This pseudo-class allows you to style the host element of a Web Component, which is the element that the component is attached to. For example:
:host {
display: block;
padding: 1rem;
background-color: #f5f5f5;
--button-bg: #eaf5c1;
--button-color: black;
}
:host-context()
: This pseudo-class allows you to style the host element based on its context, which is the elements that the host element is a descendant of. For example:
:host-context(.dark-theme) {
background-color: #333;
color: #fff;
}
/*
This would apply the styles to the :host element
when it's inside an element with the dark-theme class.
*/
:host()
: Not to be confused with :host
as this one is a "function", this pseudo-class allows you to target the host element based on its state. For example:
:host(:hover) {
background-color: #ccc;
}
::slotted()
: This pseudo-element allows you to style the slotted content of a Web Component, which is the content that's projected into the component's shadow tree. For example:
/* Selects any element placed inside a slot */
::slotted(*) {
font-weight: bold;
}
/ Selects any placed inside a slot / ::slotted(span) { font-weight: bold; }
In addition to accessing the shadow root of a web component, you can also select the web component itself from one of its children using the getRootNode()
method. This can be useful in cases where you need to access methods or properties of the web component from within one of its children.
Example usage:
const component = childElement.getRootNode();
When defining setter and getter methods for a web component, it is crucial to understand the context of the this
keyword.
For instance, if event listeners are added inside the connectedCallback()
method, there is a possibility of mistakenly selecting the element that received the listener, instead of the web component's class object.
Here's the boilerplate code:
const templateElement = document.createElement("template");
const templateStyle = /* css */ `
user-component{
isolation: isolate;
/* Other CSS styles here */
}
`;
const templateContent = /*html */ `
<figure>
<slot name="title" />
<slot name="image" />
</figure>
`;
templateElement.innerHTML = /*html */ `
<style>
${templateStyle}
</style>
${templateContent}
`;
class UserComponent extends HTMLElement {
constructor() {
super();
//We create the cotnainer that holds the web component
const shadowRoot = this.attachShadow({ mode: "open" });
//We clone the template
const clonedTemplate = templateElement.content.cloneNode(true);
//We add it as a child of our web component
shadowRoot.appendChild(clonedTemplate);
}
static get observedAttributes() {
//We indicate the list of attributes that the custom element wants to observe for changes.
return [];
}
connectedCallback() {}
disconnectedCallback() {}
attributeChangedCallback(name, oldValue, newValue) {
switch (name) {
case "": {
//…
break;
}
default:
break;
}
}
}
customElements.define("user-component", UserComponent);
Web components
What and why?
Web Components is a suite of 3 technologies allowing you to create reusable custom elements with their functionality encapsulated away from the rest of your code and utilize them in web apps in plain JavaScript/TypeScript.
They do not require third-party libraries nor any frameworks to be used
The three technologies are:
Such as tags and attributes, example:
ℹ It is important to note that the Web Components must include a dash (
-
) in their nameIf required, attach a shadow DOM to the custom element using
element.attachShadow()
method. Add child elements, event listeners, etc., to the shadow DOM using regular DOM methods.Example:
<template>
and<slot>
elements enable you to write markup templates that are not displayed in the rendered page. These can then be reused multiple times as the basis of a custom element's structure. Example:const templateStyle =
user-component{ isolation: isolate; /* Other CSS styles here */ }
; const templateContent = ``;
templateElement.innerHTML = `
${templateContent} `
class UserComponent extends HTMLElement { constructor() { super(); const shadowRoot = this.attachShadow({ mode: "open" }); }
}
customElements.define("user-component", UserComponent );
ℹYou can install a VSCode extension named “Comment tagged templates” to give some color to the HTML and CSS added as strings
Source: https://developer.mozilla.org/en-US/docs/Web/Web_Components