LePhenix47 / Chronometer-Timer-Alarm__Younes-Lahouiti

This is a small project made in HTML, SASS and TypeScript
https://lephenix47.github.io/Chronometer-Timer-Alarm__Younes-Lahouiti/
1 stars 0 forks source link

[CONCEPT] Web components #5

Open LePhenix47 opened 1 year ago

LePhenix47 commented 1 year ago

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:

class UserComponent extends HTMLElement {…};

customElements.define("user-component", UserComponent );
<user-component age="20"></user-component>

ℹ It is important to note that the Web Components must include a dash (-) in their name

If 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:

class UserComponent extends HTMLElement {
   constructor() {
    super();
    const shadowRoot = this.attachShadow({ mode: "open" });
  }

}

customElements.define("user-component", UserComponent );

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 );

```html
<user-component age="20">
  <figcaption name="title">Younes Lahouiti</figcaption>
  <img src=… alt=… name="image" />
</user-component>

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

LePhenix47 commented 1 year ago

How?

Web Components have a lifecycle, and there are several methods that can be implemented to customize their behavior:

ex:

attributeChangedCallback(name, oldValue, newValue){
  switch(name){

  case "age":{
  //…
    break;
  }
   default: break;
  }
}

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.

LePhenix47 commented 1 year ago

Styling

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.

CSS Pseudo:classes

Here are some of the most commonly used CSS pseudo-classes for Web Component styling:

CSS Pseudo::elements

/ Selects any placed inside a slot / ::slotted(span) { font-weight: bold; }

LePhenix47 commented 1 year ago

Trivial information

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.

LePhenix47 commented 1 year ago

Boilerplate code

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);