When it comes to one of the hottest trends or front-end frameworks in recent years, the first thing that comes to mind is components and the React framework that promotes componentized development. This article introduces the Web Components specification and discusses several features of Components.

preface

Before we begin this reading, let me ask you a question: What is a component?

A component is an encapsulation of data and methods that defines the functionality, presentation and use of a reusable software element, usually represented as one or a group of reusable elements.

What are the characteristics of the component? It can usually be summarized as follows:

  1. Extensibility: Since a component is developed for a specific function or requirement, it must be easy to develop and extend;
  2. Encapsulation: components as an independent whole for use, should be internal modification, external closed, only for use, without the use of the environment side effects;
  3. Ease of use: The purpose of components is to produce reusable independent parts that must provide a simple and quick way to use them.

Componentization, which brings great efficiency improvement to front-end development, is the trend of Web development in recent years. Various componentized USER interface libraries and frameworks emerge in an endless stream, such as React, Vue,Ionic, etc. These frameworks have their own implementations, concepts and programming specifications about componentization. Debate between supporters of framework is always constantly, and to switch between the different frameworks, costs are high, because, after all, everyone hopes to account for the mainstream, occupy absolute advantage position, like the current Internet explorer and netscape, until now, all kinds of standards compliant browser over-soul, in recent years, the w3c constantly to try for web standards, Web Components is a standard for componentization that is intended to bring better componentization into Web development, while trying to ensure that standards are standardized so that developers can focus on development rather than framework selection and debate.

Web components characteristics

Web Components adds a set of features to the HTML and DOM specifications that give developers the freedom to create reusable elements or parts in Web applications or documents. It consists of four parts:

  • Custom Elements: A set of apis that define new HTML Elements;
  • Shadow DOM: Encapsulation of DOM and style by composition;
  • HTML Imports: Defines how to import other HTML documents into a document;
  • HTML Templates: DOM Templates within HTML, in<template>Element declaration.

Custom Elements (Custom Elements)

Custom elements allow developers to define a class of new HTML elements and declare their behavior and style. Custom elements fall into two categories:

  • Autonomous Custom Elements: A new tag element that is completely independent of the original HTML element tag and whose behavior is defined by the developer;
  • Customized built-in: A Customized element based on the HTML original element tag to use the features of the original element. The developer only needs to define the extension behavior.

With support for creating custom elements, Web Components make component development more extensible.

Create custom tag elements

To create a custom tag element, we need to inherit the HTMLELement class. For example, on many pages we often have a one-click back to the top feature. We create a component that returns to the top:


    class GoTop extends HTMLElement {
        constructor() {
            super(a); } } customElements.define('go-top', GoTop);Copy the code

In pages where you want to use this component just as you would with a normal HTML element:


    <go-top>Top</go-top>Copy the code

Of course, all the styles, behaviors, event listeners, and default behaviors of this element need to be defined by the developer. You can’t expect it to have default behaviors like

Create custom built-in elements

Most of the time we don’t need to completely create a new element, but we just need to extend some of the built-in elements to create custom built-in elements that inherit from the class, such as HTMLButtonElement or HTMLDivElement:


    class MenuButton extends HTMLButtonElement {... } customElements.define('menu-button', MenuButton);Copy the code

It is also easy to use, with the same syntax as the built-in elements; The difference is that when a custom built-in element is needed, the is attribute is added to the built-in element, whose value corresponds to the name of the custom built-in element created:


    <button is="menu-button">menu</button>Copy the code

The default behavior of this element is inherited from the

contrast

As can be seen from the above example, there are two main differences between custom tag elements and built-in elements:

  • Tag: The custom tag element is a completely independent new element, the new tag, and the custom built-in tag, using the existing built-in tag;
  • Behavior and style: Custom built-in elements inherit the default behavior, style and semantics of built-in elements and can be extended, while custom tag elements need to be defined by the developer.

Shadow DOM

DOM, also known as document object model, is a structural representation of HTML documents. It represents a document in a tree structure. The DOM specification provides a set of apis that allow us to manipulate document nodes, commonly known as DOM apis.

Unlike JavaScript, where functions form a single scope, the concept of local scope does not exist in the hierarchy of the DOM tree of a document. That is, all styles defined in a document have an effect on the entire document. Styles in the document also affect declared styles within the component, regardless of where the element is located. This obviously greatly interferes with the independence and reusability of the component. This was an issue that had to be addressed, but don’t worry, this has been addressed with the attachShadow() method described below.

The shadow DOM API provides the attachShadow() method, which creates a shadow DOM and allows the content or component to be attached to an HTML document as a separate DOM subtree.

create

To create a shadow DOM, we simply use the attachShadow() method, but note that all shadow DOM must be bound to an element that exists in the document (either HTML built-in or custom) :


    var frag = document.createElement('div');
    var shadowRoot = frag.attachShadow({mode: 'open'});
    shadowRoot.innerHTML = '<p>Shadow DOM Content</p>';Copy the code

Shadow Tree and Shadow Host

The element created using attachShadow() above is a shadow DOM, and its child content forms a shadow tree. The element bound to the shadow DOM, that is, the element in the document containing the tree, is usually called shadow host.

Slots

As shown above, when an element (the shadow body) contains a shadow DOM, the browser default renders only the shadow tree of the shadow DOM, and does not render other children of the shadow body. For example, an element


    <div class="menus">
        <h2>Menus</h2>
    </div>Copy the code

Bind shadow DOM to this element:


    var menus = document.querySelector('.menus');
    var shadowRoot = menus.attachShadow({mode: 'open'});
    shadowRoot.innerHTML = '
      
    \
  • Home
  • \
  • About
  • \
'
;Copy the code

The shadow tree content is:


    <ul>
        <li>Home</li>
        <li>About</li>
    </ul>Copy the code

The final render result is as follows:


    <div class="menus">
        <ul>
            <li>Home</li>
            <li>About</li>
        </ul>
    </div>Copy the code

Hello! The original child element content of the shadow body is not rendered, so is there nothing to be done? Of course not. If you want to save the child content, you need to use the

slot element, which acts as a placeholder. Just change the previous shadow body content to the following:


    <div class="menus">
        <h2>Menus</h2>
        <slot></slot>
    </div>Copy the code

The render results are as follows, and everything fits the requirements:


    <div class="menus">
        <h2>Menus</h2>
        <ul>
            <li>Home</li>
            <li>About</li>
        </ul>
    </div>Copy the code
Named slots

The example shown above has only one slot. What if multiple groups are required? Web Components also has a solution, which is to use named slots, that is, to add the name attribute to the slot, again using the example above, modify the shadow body content:


    <div class="menus">
        <slot></slot>
        <slot name="top"></slot>
        <slot name="right"></slot>
    </div>Copy the code

Suppose the shadow tree contains the following contents:


    <h2>Menus</h2>
    <ul slot="top">
        <li>Home</li>
        <li>About</li>
    </ul>
    <ul slot="right">
        <li>Home</li>
        <li>Top</li>
    </ul>Copy the code

Render the result as follows:


    <div class="menus">
        <h2>Menus</h2>
        <ul>
            <li>Home</li>
            <li>About</li>
        </ul>
        <ul>
        <li>Home</li>
        <li>Top</li>
    </ul>
    </div>Copy the code

As shown above, the slot with the name attribute is replaced by a shadow subtree with the same value of the slot attribute. By default, the remaining content is replaced by an empty slot. If no empty slot exists, the remaining content is discarded.

style

As mentioned above, the styling of the component defined by Web Components is independent of the styling of the external environment.

<head> <style> .top {margin-top: 30px; } </style> </head> ... <div class="top"> ... </div> ... <div class="menus"> #shadow-root <style> .top {margin-top: 10px; } </style> <div class="top"> ... </div> </div>Copy the code

In the example above, the margin-top value of the top element inside the component is 10px, while the margin-top value of the top element outside the component is 30px, and the two are independent.

Apply colours to a drawing

The rendering of the shadow DOM tree is no different from the rendering of the Web document DOM tree, which is rendered by the browser rendering engine. It should be noted that the DOM rendering process of the shadow tree and the rendering of the document DOM tree are carried out separately.

HTML Imports

How do I introduce another Web document or web component into an HTML document? Languages like JSP or PHP have extended HTML syntax to include tags such as

directly into another document. However, prior to this, the native HTML specification did not support directly importing another document’s content, which usually required ajax requests. The content is then inserted through JavaScript using the DOM API, which is obviously not the desired result for componentization development and usage. This is a deviation from the ease of use of components, so HTML imports define how to introduce and reuse another document within a document.

To introduce a document or Web component directly into the document, use the following syntax, using the tag:


    <link rel="import" href="components.html">Copy the code

If you define a got-top custom element in components.html, you can use it directly in this document:


    <go-top>GoTop</go-top>Copy the code

As above, just set the rel attribute of the tag to import. It is also worth noting that the import method skips the loading and execution of loaded documents in order to avoid repeated execution of scripts introduced into the document.

HTML Templates

In order to be more user-friendly with component templates, the Web Components specification supports the


    <template id="menusTemplate">
        <ul>
            <li>Home</li>
            <li>About</li>
        </ul>
    </template>Copy the code

Using script operations, the element content property accesses template content:


    var menusTemplate = document.querySelector('#menusTemplate');
    var frag = document.importNode(menusTemplate.content, true);
    document.querySelector('.menus').appendChild(frag);Copy the code

The template tag

The

  1. <template>The contents of the tag will not be rendered;
  2. Tag inside the image, such as media resources will not be loaded;
  3. Tags do not appear in the DOM tree and are not visible to the review element;

About Compatibility

With respect to the compatibility of Web Components specification, it is necessary to use WebComponentsJS polyfills to support development. Generally speaking, Safari 10 and Google Chrome (53) are more compatible. Although compatibility is not good, it is still a work in progress, but it is necessary to learn.

The class library

Several common Web component libraries are recommended:

  • Polymer: Web component library from Google, supporting unidirectional and bidirectional binding of data, good compatibility and good cross-browser performance;
  • X-tag: Open source library launched by Microsoft, supporting the Web Components specification, compatible with Web ComponentsAPI;
  • Slim.js: A lightweight Web component library that focuses on helping developers write native Web components without relying on other frameworks, but also provides good extensibility that developers can expand freely.

reference

  1. Component
  2. Web Components Specifications
  3. Web Components WiKi
  4. Web Components MDN

Welcome to visit my personal blog – Xiong Jiangang’s blog