Create inline CSS and JavaScript Custom Elements by using Custom Elements. It’s important to note that it’s not an alternative to React, Vue, or Angular frameworks; it’s a completely new concept.

Create a completely custom element

CustomElementRegistry object

The customElements attribute is exposed under the Window global object, through which the CustomElementRegistry object can be accessed. There are several methods under the CustomElementRegistry object to register Custom Elements and query Custom Elements:

  • define()Use to define a new Custom Element
  • get()Constructor for getting a Custom Element, returning undefined if none exists
  • upgrade()Used to upgrade Custom Elements
  • whenDefined()Constructor for getting Custom elements, similar to get() except that the return value is promise and the available values return at this point or at this point

How do I create a Custom Element

In the call window. CustomElements. Define () method before, first of all to define a new HTML element

class CustomTitle extends HTMLElement {
    // ToDo...
}
Copy the code

Use the Shadow DOM in the constructor of the CustomTitle class to associate custom CSS, JavaScript, and HTML to the new element, so that you can encapsulate various functions in this new element, first initializing the constructor

class CustomTitle extends HTMLElement {
    constructor() {
        super(a)/ /...}}Copy the code

AttachShadow () is then called with the parameter {mode: ‘open’}. This attribute sets the encapsulation mode of the shadow DOM. If it is set to open, access to the element’s shadowRoot attribute is available, but if it is set to close, it is not.

class CustomTitle extends HTMLElement {
    constructor() {
        super(a)this.attachShadow({ mode: 'open' })
        / /...}}Copy the code

Next, set the HTML for the element

class CustomTitle extends HTMLElement {
    constructor() {
        super(a)this.attachShadow({ mode: 'open' })
        this.shadowRoot.innerHTML = ` 

Hello WC!

`
}}Copy the code

The innerHTML here can write multiple HTML tags

Once you have defined the built-in elements, use window.customElements

window.customElements.define('custom-title', CustomTitle)
Copy the code

The above can be used in the page

Add CSS

class CustomTitle extends HTMLElement {
  constructor() {
    super(a)this.attachShadow({ mode: 'open' })
    this.shadowRoot.innerHTML = `  

Hello WC!

`
}}Copy the code

Shorthand syntax

window.customElements.define('custom-title'.class extends HTMLElement {
  constructor() {... }})Copy the code

Add JavaScript

The method of adding JavaScript is slightly different from that of CSS. It cannot write directly into the template string, but needs to add addEventListener

class CustomTitle extends HTMLElement {
    constructor() {
        super(a)this.attachShadow({ mode: 'open' })
        this.shadowRoot.innerHTML = `  

Hello WC!

`
this.addEventListener('click', e => { console.log('clicked')}}}Copy the code

The demo link

Use the template

You can use template, specified by id to

<template id="custom-title-template">
  <style>
    h1 {
        font-size: 40px;
        color: # 000;
    }
  </style>
  <h1>Hello WC!</h1>
</template>

<custom-title></custom-title>
Copy the code

It then references the Shadow DOM in the Custom Element constructor

class CustomTitle extends HTMLElement {
    constructor() {
        super(a)this.attachShadow({ mode: 'open' })
        const tmpl = ducument.querySelector('#custom-title-template')
        this.shadowRoot.appendChild(tmpl.content.cloneNode(true))}}window.customElements.define('custom-title', CustomTitle)
Copy the code

The demo link

The life cycle

In addition to constructor, you can define lifecycle functions that execute a particular method at a particular time

  • connectedCallbackExecuted when the element is inserted into the DOM
  • disconnectedCallbackExecuted when an element is deleted from the DOM
  • attributeChangedCallbackExecuted when a change or addition or deletion of a property is detected (passing in 3 parameters)
    • AttrName: Changed attribute name
    • OldVal: the value before the property changed
    • NewVal: the changed value of the property
  • adoptedCallbackWhen the element hasWhen moving to a new document
class CustomTitle extends HTMLElement {
    constructor() {
      / /...
    }
  
    connectedCallback() {
      / /...
    }
  
    disconnectedCallback() {
      / /...
    }
    
    attributeChangedCallback(attrName, oldVal, newVal) {
      / /...}}Copy the code

As mentioned above, attributeChangedCallback listens for changes in attribute values. To define the range of listening attribute values, you must define a static method that returns an array of listening attributes

class CustomTitle extends HTMLELement {
    constructor() {
      / /...
    }
    
    static get observedAttributes() {
      return ['diabled']
    }
    
    attributeChangedCallback() {
      / /...}}Copy the code

Here I define the disabled property to be listened on when its value changes, such as when its value is true

document.querySelector('custom-title').disabled = true
Copy the code

At this point, attributeChangedCallback is triggered, with the three parameters ‘disabled’, false, and true, respectively

Define custom properties

Define custom properties on custom elements by adding getter and setter functions to define custom properties on custom elements

class CustomTitle extends HTMLElement {
    static get observedAttributes() {
        return ['nbattribute']
    }
    
    get nbattribute() {
        return this.getAttribute('nbattribute')
    }
    
    set nbattribute(value) {
        this.setAttribute('nbattribute', value)
    }
}
Copy the code

If a Boolean property value such as disabled is defined, the property value is displayed if true and not if false

class CustomTitle extends HTMLElement {
    static get observedAttributes() {
        return ['boolattribute']
    }
    
    get boolattribute() {
        return this.hasAttribute('boolattribute')
    }
    
    set boolattribute(value) {
        if (value) {
            this.setAttribute('boolattribute'.' ')}else {
            this.removeAttribute('boolattribute')}}}Copy the code

Styles custom elements that have not yet been defined

During page loading, JavaScript takes time to load and custom elements are not yet defined. When the page is loaded, the layout of the page may not be so friendly. To solve this problem, add :not(:defined) pseudo-classes and set a rough height and gradient effect

custom-title:not(:defined) {
    display: block;
    height: 400px;
    opacity: 0;
    transition: opacity 0.5 s ease-in-out;
}
Copy the code

Browser Supportcaniuse

Latest versions of FireFox, Safari, Chrome, Edge rewritten with Chromium kernel, IE (forget it), and polyfill for older browsers

Create built-in elements for customization functionality

The essence element of the so-called customization function refers to the customization function of the existing elements in HTML and the extension of the existing elements. Attach features such as constructors and lifecycle hooks to existing elements. Creating custom built-in elements is different from fully custom elements, as shown below. To extend Button functionality, first you need to define a class that inherits HTMLButtonElement instead of HTMLElement

class PlasticButton extends HTMLButtonElement {
     constructor() {
        super(a)this.addEventListener('click', e => {
    	  // Do something }}})// When you define a custom element, you add the extends parameter
customElement.define('plastic-button', PlasticButton, { extends: 'button' })
Copy the code

There is also a difference in usage, using the IS attribute on the original element to specify the extended element

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

Browser Supportcaniuse

Latest versions of FireFox, Safari, Chrome, Edge rewritten with Chromium kernel, IE (forget it), and polyfill for older browsers

Web Components related libraries

  • Hybrids is a UI library for creating Web Components with simple and functional API.
  • LitElement uses lit-html to render into the element’s Shadow DOM and adds API to help manage element properties and attributes. Polymer provides a set of features for creating custom elements.
  • Slim.js is an opensource lightweight web component library that provides data-binding and extended capabilities for components, using es6 native class inheritance.
  • Stencil is an opensource compiler that generates standards-compliant web components.

reference

  • www.webcomponents.org/introductio…
  • The w3c. Making. IO/webcomponen…