Web Components are a different set of technologies that allow you to create reusable custom elements whose functionality is encapsulated outside of your code and use them in your Web applications.
Concepts and Usage
As developers, we all know it’s a good idea to reuse as much code as possible. This is often not so easy for custom tag structures — think of complex HTML (and associated styles and scripts), sometimes you have to write code to render custom UI controls, and using them multiple times can mess up your pages if you’re not careful.
Web Components aims to solve these problems — it consists of three main techniques that can be used together to create custom elements that encapsulate functionality and can be reused anywhere you like without worrying about code conflicts.
Custom elements
Custom Elements: A set of JavaScript apis that allow you to define custom elements and their behavior, and then use them as needed in your user interface.Shadow DOM
Shadow DOM: A set of JavaScript apis for attaching a wrapped “shadow” DOM tree to an element (rendered separately from the main document DOM) and controlling its associated functionality. This way, you can keep the functionality of elements private so that they can be scripted and styled without fear of running afoul of the rest of the document.HTML templates
HTML template:<template>
和<slot>
The element lets you write tag templates that are not displayed on rendered pages. They can then be reused many times as a basis for custom element structures.
The basic approach to implementing a Web Component is usually as follows:
- Create a class or function to specify the functionality of the Web component (if you use classes, use ECMAScript 2015 class syntax).
- use
CustomElementRegistry.define()
Method registers your new custom element and passes it the name of the element to be defined, the class that specifies the element’s functionality, and optionally the element it inherits from. - Use if needed
Element.attachShadow()
The Shadow DOM () method attaches a shadow DOM to the custom element. Add child elements, event listeners, and so on to the Shadow DOM using the usual DOM methods. - Use if needed
<template>
和<slot>
Define an HTML template. Clone the template again using normal DOM methods and attach it to your Shadow DOM. - Use custom elements wherever you like on the page, just as you would use regular HTML elements.
The life cycle
Special callback functions defined in the class definition of a custom element that affect its behavior: • connectedCallback: called when the custom element is first connected to the document DOM. • disconnectedCallback: Called when the custom element is disconnected from the document DOM. • adoptedCallback: called when a custom element is moved to a new document. • attributeChangedCallback: as a custom attributes are added, removed or change is invoked.
attributeChangedCallback > connectedCallback > disconnectedCallback
The selector
:defined
: Matches any defined element, including built-in elements and usageCustomElementRegistry.define()
Define a custom element.:host
: Selects the current custom element:host()
Select the shadow host of the shadow DOM, and the content in () is the CSS it uses internally (so you can select custom elements from within the Shadow DOM) — but only the shadow Host element that matches the selector of the given method. Such as::host(name="hello")
.:host-context()
: Select the shadow host of the Shadow DOM, which is the CSS it uses internally (so you can select custom elements from within the Shadow DOM) — but only match the child shadow host element of the matching element with the selector of the given method.
The sample
Now that you know the basics, let’s implement what a basic drop-down selection component (including select and Option) does
- Add change event
- Displays/hides the drop-down list box
- Assign input when option is clicked
- Click on other areas to hide drop-down boxes
The specific implementation
Basic style
class Select extends HTMLElement {
constructor() {
// The super method must be called first
super(a);// The function code of the element is written here
const template = document.createElement("template");
template.innerHTML = `
`;
const shadowELe = this.attachShadow({ mode: "open" });
const content = template.content.cloneNode(true); shadowELe.appendChild(content); }}class Option extends HTMLElement {
constructor() {
// The super method must be called first
super(a);// The function code of the element is written here
const template = document.createElement("template");
template.innerHTML = `
`;
const shadowELe = this.attachShadow({ mode: "open" });
const content = template.content.cloneNode(true);
shadowELe.appendChild(content);
}
static get observedAttributes() {
return ["value"];
}
}
customElements.define("ivy-select", Select);
customElements.define("ivy-option", Option);
Copy the code
Add event
class Select extends HTMLElement {
constructor() {
// The super method must be called first
super(a);// The function code of the element is written here.this.$input = shadowELe.querySelector(".select-inner");
this.dropEle = shadowELe.querySelector(".drop");
this.value === null;
this.$input.addEventListener("click".() = > {
this.dropEle.style.display = "block";
});
this.dropEle.addEventListener("click".(ev) = > {
const target = ev.target;
const nodeName = target.nodeName.toLowerCase();
if (nodeName === "ivy-option") {
this.value = target.getAttribute("value");
this.$input.setAttribute("value", target.innerHTML);
// Custom events
this.dispatchEvent(
new CustomEvent("change", {
detail: {
value: this.value,
},
})
);
this.dropEle.style.display = "none"; }});this.BodyClick = () = > {
this.dropEle.style.display = "none";
};
}
connectedCallback() {
document.addEventListener("click".this.BodyClick, true);
}
disconnectedCallback() {
document.removeEventListener("click".this.BodyClick); }}Copy the code
Note that if you want to trigger the attributeChangedCallback() callback after an element attribute changes, you must listen for this attribute. This is done by defining the get observedAttributes() function, which contains a return statement that returns an array containing the names of the attributes to listen on: observedAttributes() static get observedAttributes() {return [‘value’]; }
Full code: Portal