Web Components Three Key Technologies

Web Components is a set of standard technologies used to create reusable custom HTML elements. They can encapsulate complex functionality and be used across different pages and applications.
Web Components consist of three main technologies: Custom Elements, Shadow DOM, and HTML Templates.

1. Custom Elements

Custom Elements allow developers to define custom HTML elements that can be used within a page. These elements can encapsulate arbitrary behavior and functionality, which can then be manipulated and controlled via JavaScript.

For example, the following code defines a custom element my-button that inherits from HTMLButtonElement. When clicked, it displays an alert dialog:

class MyButton extends HTMLButtonElement {
  constructor() {
    super();
    this.addEventListener('click', () => alert('Button clicked!'));
  }
}
customElements.define('my-button', MyButton, { extends: 'button' });

The above code defines a custom element MyButton using ES6 class syntax that inherits from HTMLButtonElement. Inside the constructor, an event listener is attached to listen for click events, and upon triggering, an alert dialog appears. Finally, the customElements.define() method registers this custom element into the document under the name my-button, extending it from a standard button element.

2. Shadow DOM

Shadow DOM enables developers to create encapsulated DOM trees that isolate the styles and behavior of custom elements. This ensures that when these elements are used in a page, they remain unaffected by external styles or scripts.

For example, the following code defines a custom element my-progress that uses Shadow DOM to encapsulate a progress bar:

class MyProgress extends HTMLElement {
  constructor() {
    super();
    const shadow = this.attachShadow({ mode: 'open' });
    
    const template = document.createElement('template');
    template.innerHTML = `
      <style>
        :host {
          display: block;
          width: 100%;
          height: 12px;
          border-radius: 6px;
          background-color: #eee;
        }
        #inner {
          display: block;
          width: ${this.getAttribute('value')}%;
          height: 100%;
          border-radius: 6px;
          background-color: #007aff;
        }
      </style>
      <div id="inner"></div>
    `;
    
    shadow.appendChild(template.content.cloneNode(true));
  }

  static get observedAttributes() {
    return ['value'];
  }

  attributeChangedCallback(name, oldValue, newValue) {
    if (name === 'value') {
      this.shadowRoot.querySelector('#inner').style.width = newValue + '%';
    }
  }
}
customElements.define('my-progress', MyProgress);

The above code defines a custom element MyProgress using ES6 class syntax that inherits from HTMLElement. In the constructor, it creates a Shadow DOM instance with an 'open' mode, allowing external access to the shadow content. An HTML template is then created containing both the styling and structural markup for the progress bar, which is appended into the Shadow DOM. Finally, the custom element is registered in the document using customElements.define() under the name my-progress.

3. HTML Templates

HTML Templates allow developers to create reusable HTML templates that can contain arbitrary HTML, CSS, and JavaScript code. These templates can be instantiated and utilized whenever needed.

For example, the following code defines an HTML template named my-template, which includes a button and a text input field:

const template = document.createElement('template');
template.innerHTML = `
  <style>
    button {
      background-color: #007aff;
      color: #fff;
      border: none;
      border-radius: 4px;
      padding: 8px 16px;
      font-size: 16px;
      cursor: pointer;
    }
    input {
      border: 1px solid #ccc;
      border-radius: 4px;
      padding: 8px;
      font-size: 16px;
    }
  </style>
  <button>Click me</button>
  <input type="text" placeholder="Enter your name">
`;

document.body.appendChild(template.content.cloneNode(true));

The above code creates an HTML template containing a button and a text input. During the creation of the template, its content is set using the innerHTML property of the <template> element. Subsequently, this template is added to the document body via the document.body.appendChild() method.

It should be noted that defining an HTML Template does not automatically instantiate it; developers must use JavaScript code to explicitly instantiate and insert the template into the DOM as needed.