This is the 14th day of my participation in the August More Text Challenge. For details, see: August More Text Challenge

web component

Talk about what a Web Component is, what benefits it has, and how to integrate existing Web technologies to implement a Web Component

What is a Web Component

A component is platform independent, that is, a component is platform independent. Components are designed to encapsulate a component’s code into a beautiful, reusable package that is usable enough. In other words, we design components to meet the requirements of different teams, and provide the same standard component for different teams to call

Why Web Component

Why is a Web Component? What is a Web Component good?

  • Maximizing interoperability, the ability to encapsulate components and provide component behaviors through Web Components, and for a company with multiple products, consistency of user experience across products through Web Components, such as login processes, This not only saves the team development cost, but also saves the cost for users to learn different products because of the consistency of some processes or operations, thus providing a good user experience.
  • Better Performance: To make this easier to understand, the Web Component, because of its native browser support, is written directly in JS, which is strongly encouraged and fully supported by browsers, and naturally has its own performance advantage over frameworks such as Vue, React, and Angular Components. Because the component in the framework depends on the framework, the bundle file will need to include the Component support file, so the post-bundle JS volume will be much larger than the native JS support for the Web Component.
  • We’ve talked a lot about encapsulation before Shadow DOM
  • Styling (styling) : In today’s rich and colorful world, there are applications with outstanding personality, web applications and good apps. Everyone is striving for user experience. Of course, apps also need their own style, which is different from other apps, and these differences are also reflected in style and style. Bright theme good design is bound to give users a deep impression. So style is very important today,

The web Component is implemented based on the following techniques

HTML Template

An HTML template is a declaratively defined segment tag that the browser can parse as HTML

<template id="card-tmpl">
        <style>
            #card{
                flex-direction: row;
                background-color: lightblue;
            }
            #title{
                align-items: center;
                justify-self: center;
                color: darkslateblue;
            }
        </style>
        <div id="card">
            <h2 id="title">machine learning</h2>
            <div id="content"></div>
        </div>
    </template>
Copy the code

Var template = document.getelementById (‘card-tmpl’); var template = document.getelementByid (‘card-tmpl’) DOM element has an attribute content in the template, can get through the attribute to the template tags within the content, the DOM elements can then be const shadowRoot = this. AttachShadow ({mode: ‘open’}).appendChild(template.cloneNode(true)); Add to shadowRoot as a shadow DOM node.

custom element

We define our own HTML tag, how to create a custom element, first we create a class that inherits HTMLElement and then we get the DOM lifecycle callback, A processing task is performed when a custom element is added to or removed from the DOM.

  • ConnectedCallback: Callback when a Custom Element is first inserted into the document DOM.
  • DisconnectedCallback: Callback when a Custom Element is removed from the document DOM
  • AdoptedCallback: Callback function when a Custom Element is moved to a new document
  • AttributeChangedCallback: when a custom element increase, delete, modify its attributes of the callback is invoked

The constructor of the custom element calls its parent constructor super(). Sometimes we need to listen for a custom attribute on the element.

<my-counter style="--background-bg-color: lightblue; --btn-width:600px;" id="counter" count="10"></my-counter>
Copy the code

If we want to listen for changes to the count attribute, we need to define the following static methods in our custom element

static get observedAttributes() {return ["count"]; / / return
    }
Copy the code

Note that if you want to trigger the attributeChangedCallback() callback after an element attribute has changed, you must listen for this attribute. This can be done by defining the observedAttributes() get function. The observedAttributes() function contains a return statement that returns an array of the names of the attributes to listen on. You also need to implement the count attribute set and the get method.

    get count() {return this.getAttribute("count");
    }

    set count(val) {this.setAttribute('count',val)
    }
Copy the code

shadow DOM

Web Compoent Series – Shadow DOM(1)

ES6 module

In terms of modularity, ES6 is also quite simple

<script type="module" src="counter.js"></script>
Copy the code

If you had mentioned Web Component to people a few years ago, people would have been skeptical of the technology, because most browser versions didn’t support this new API very well and it required a lot of extra work to get you to define web Component every where, But today, almost all browsers offer good support for The Web Component.

Styling (Styling)

Style definitions are handed over to consumers via var in CSS

We want to transfer some style changes to the user of the component. We can do this by using var and then control by assigning values to these variables in the style attribute of the custom tag.

#btn{ outline:None; color:white; max-width:var(--btn-width,200px); background-color:var(--background-bg-color,green); border: 0px; padding:20px; The font - size: 1.2 em. border-radius:10px; text-align: center; }Copy the code
<my-counter style="--background-bg-color: lightblue; --btn-width:600px;" id="counter" count="10"></my-counter>
Copy the code

Use CSS parts to expose the Shadow DOM style

The purpose of the Shadow DOM is to allow HTML and CSS to have their own space inside the component, so that the styles defined outside of the component will not affect the inner parts of the custom element, here

h1{
	color: dodgerblue;
}
Copy the code

counter

my-counter::part(title){
	color: dodgerblue;
}
Copy the code
render(){
        
        this.shadowRoot.innerHTML = ` <style> *{ box-sizing: border-box; margin:0; padding:0; box-sizing: border-box; } .container{ display:flex; flex-direction:column; align-items: center; justify-content: center; } #btn{ outline:None; color:white; max-width:var(--btn-width,200px); background-color:var(--background-bg-color,green); border: 0px; padding:20px; The font - size: 1.2 em. border-radius:10px; text-align: center; } span {the font - size: 2.75 em; font-weight:bold; <div class="container"> <h1 part="title"> <span>The ${this.count}</span>
        <button id="btn">Increment</button> 
        </div>
        `
    }
Copy the code

The complete code

<! DOCTYPEhtml>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="Width = device - width, initial - scale = 1.0">
    <title>web component</title>
    <style>* {margin: 0;
            padding: 0;
        }
        /* my-counter{ width: 100vw; } * /
        my-counter::part(title){
            color: dodgerblue;
        }
    </style>
</head>
<body>
    <template>
        <div>
            <div>template</div>
        </div>
    </template>
    <my-counter style="--background-bg-color: lightblue; --btn-width:600px;" id="counter" count="10"></my-counter>
    <! -- <button onclick="update"></button> -->
    <script type="module" src="counter.js"></script>

    <script>
        function update(){

            let counter = document.querySelector("#counter")}</script>
</body>
</html>
Copy the code

// custom element
// Define a class that inherits HTMLElment

class MyCounterElement extends HTMLElement{
    constructor(){
        // Call the superclass constructor
        super(a);// Add shadow DOM, element. Add shadow DOM shadowRoot
        // Form a scope, style and event misunderstanding affect outside the scope, thus forming closure
        this.attachShadow({mode:'open'})
        // this.shadowRoot
        // this.template = document.querySelector("#counter");
        // this.template.content;
        // slot 

    }
    get count() {return this.getAttribute("count");
    }

    set count(val) {this.setAttribute('count',val)
    }

    // Static method, watch count
    /** * Note that if you want to trigger the attributeChangedCallback() callback after an element attribute has changed, * you must listen for this attribute. This can be done by defining the observedAttributes() get function. The observedAttributes() function contains a return statement in its body that returns an array containing the names of the attributes to be listened on */
    static get observedAttributes() {return ["count"]; / / return
    }

    bindBtn(){
        let btn = this.shadowRoot.querySelector("#btn");
        btn.addEventListener('click'.this.increment.bind(this));
    }

    attributeChangedCallback(prop, oldVal, newOld){
        if (prop === "count") {this.render();
            this.bindBtn(); }}increment(){
        this.count++;
    }
    // Called when the Custom Element is first inserted into the document DOM.
    connectedCallback(){
        / / rendering
        this.render();
        // Bind the event
        this.bindBtn();
    }

    render(){
        
        this.shadowRoot.innerHTML = ` <style> *{ box-sizing: border-box; margin:0; padding:0; box-sizing: border-box; } .container{ display:flex; flex-direction:column; align-items: center; justify-content: center; } #btn{ outline:None; color:white; max-width:var(--btn-width,200px); background-color:var(--background-bg-color,green); border: 0px; padding:20px; The font - size: 1.2 em. border-radius:10px; text-align: center; } span {the font - size: 2.75 em; font-weight:bold; <div class="container"> <h1 part="title"> <span>The ${this.count}</span>
        <button id="btn">Increment</button> 
        </div>
        `
    }
    
}

customElements.define('my-counter',MyCounterElement);

Copy the code