Web Components are a collection of 4 native web APIs. They are:
ES Modules
Custom Elements
Shadow DOM
HTML Templates
You've already used the ES modules specification, which allows you to create javascript modules with imports and exports that are loaded into the page with <script type="module">
The Custom Elements specification lets users define their own HTML elements using JavaScript. The names must contain a hyphen ( -
) to differentiate them from native browser elements. Clear the index.js
file and define a custom element class:
class RatingElement extends HTMLElement {}
customElements.define('rating-element', RatingElement);
A custom element is defined by associating a class that extends HTMLElement
with a hyphenated tag name. The call to customElements.define
tells the browser to associate the class RatingElement
with the tagName ‘rating-element'
. This means that every element in your document with the name <rating-element>
will be associated with this class.
Place a <rating-element>
in the document body and see what renders.
<body>
<rating-element></rating-element>
</body>
Now, looking at the output, you'll see that nothing has rendered. This is expected, because you haven't told the browser how to render <rating-element>
. You can confirm that the Custom Element definition has succeeded by selecting the <rating-element>
in Chrome Dev Tools' element selector and, in the console, calling:
$0.constructor
Which should output:
class RatingElement extends HTMLElement {}
Custom Elements come with a set of lifecycle hooks. They are:
constructor
connectedCallback
disconnectedCallback
attributeChangedCallback
adoptedCallback
The constructor
is called when the element is first created: for example, by calling
document.createElement(‘rating-element')
or new RatingElement()
. The constructor is a good place to set up your element, but it is typically considered bad practice to do DOM manipulations in the constructor for element "boot-up" performance reasons.
The connectedCallback
is called when the custom element is attached to the DOM. This is typically where initial DOM manipulations happen.
The disconnectedCallback
is called after the custom element is removed from the DOM.
The attributeChangedCallback(attrName, oldValue, newValue)
is called when any of the user-specified attributes change.
The adoptedCallback
is called when the custom element is adopted from another documentFragment
into the main document via adoptNode
such as in HTMLTemplateElement
.
Now, return to the custom element and associate some DOM with it. Set the element's content when it gets attached to the DOM:
class RatingElement extends HTMLElement {
constructor() {
super();
this.rating = 0;
}
connectedCallback() {
this.innerHTML = `
Internal Content
`;
}
}
customElements.define('rating-element', RatingElement);
In the constructor
, you store an instance property called rating
on the element. In the connectedCallback
, you add DOM children to <rating-element>
to display the current rating, together with thumbs up and thumbs down buttons.