CustomElements is a new API under the Web Components specification that can be used for componentized development.
If your app only works with the latest Chrome browser, it’s a great alternative to React or Vue.
Basic usage
The component declaration is in an HTML file. Components include styles (Style), nodes (DOM), and interaction logic (Script). The basic structure of a component file is as follows:
<template>
<style></style>
<div>DOM node</div>
</template>
<script>
const componentDocument = document.currentScript.ownerDocument;
class Component extends HTMLElement {
static get TAG_NAME() {
return 'component-tag-name';
};
constructor() {
super(a);const shadow = this.attachShadow({ mode: 'closed' });
const content = componentDocument.querySelector('template').content.cloneNode(true);
shadow.appendChild(content);
}
}
customElements.define(Component.TAG_NAME, Component);
</script>
Copy the code
The template node contains the Style (Style) and node (DOM). The interaction logic is in the script tag.
Component files are imported into HTML files by . The way to use components in HTML files is to write component tags directly. Such as:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0">
<title>HTML</title>
<link rel="import" href="./component.html">
</head>
<body>
<component-tag-name></component-tag-name>
</body>
</html>
Copy the code
The component registration
The customElements. Define API is used to catalog components. The API accepts three parameters: the component label name, the component’s class, and the label type that the component inherits. Such as:
customElements.define('expanding-list', ExpandingList, { extends: "ul" });
Copy the code
The component constructor class is ExpandingList. The component inherits ul label features.
Component constructor class
A component’s building class needs to inherit from the HTMLElement class, or it can inherit from a subclass of HTMLElement, such as HTMLParagraphElement. If you inherit the class HTMLParagraphElement, a component has the features of a P tag.
class Component extends HTMLElement {
constructor() {
super(a);const shadow = this.attachShadow({ mode: 'closed' });
const content = componentDocument.querySelector('template').content.cloneNode(true); shadow.appendChild(content); }}Copy the code
The constructor inside the component is required. Inside the constructor, we call the parent class’s constructor, create a Shadow DOM node, and add the component template content to the node.
Using Shadow DOM, the styles inside the component and outside the component do not interfere with each other, which makes component encapsulation more complete.
We can through the document. CurrentScript. OwnerDocument; To get the nodes of the template itself.
Component attributes
Components can use attributes just like HTML tags. Properties can be obtained from components.
<component-tag-name attr-name="attr-value"></component-tag-name>
Copy the code
class Component extends HTMLElement {
constructor() {
super(a);const shadow = this.attachShadow({ mode: 'closed' });
const content = componentDocument.querySelector('template').content.cloneNode(true);
shadow.appendChild(content);
const attrValue = this.getAttribute('attr-name'); }}Copy the code
Component life cycle
connectedCallback
Component mount, triggered after component initialization and when movingdisconnectedCallback
Component uninstalladoptedCallback
The component is moved to a new document treeattributeChangedCallback
Component property changes
Component events
Custom events can be triggered.
<template>
<style></style>
<button>Component events</button>
</template>
<script>
const componentDocument = document.currentScript.ownerDocument;
class Component extends HTMLElement {
static get TAG_NAME() {
return 'component-tag-name';
};
static get BUTTON_CLICK() {
return 'button-click';
}
constructor() {
super(a);const shadow = this.attachShadow({ mode: 'closed' });
const content = componentDocument.querySelector('template').content.cloneNode(true);
shadow.appendChild(content);
const button = shadow.querySelector('button');
button.addEventListener('click', () = > {this.dispatchEvent(new CustomEvent(Component.BUTTON_CLICK, { button }));
});
}
}
customElements.define(Component.TAG_NAME, Component);
</script>
Copy the code
example
- A basic example of customElements
- Sample indexedDB implemented with customElements