Using innerHTML
and template literal strings with no sanitization may cause security issues with script injection. Methods in the past have included using DocumentFragments
, but these also come with other issues such as images loading and scripts running when the templates are defined as well as introducing obstacles for reusability. This is where the <template>
element comes in; templates provide inert DOM, a highly performant method to clone nodes, and reusable templating.
Next, transition the component to use HTML Templates:
<!DOCTYPE html>
<head>
<script src="./index.js" type="module"></script >
<style>
span{
border: 1px solid red;
}
</style>
</head>
<body>
<rating-element></rating-element>
</body>
Here you moved the DOM content into a template tag in the main document's DOM. Now refactor the custom element definition:
class RatingElement extends HTMLElement {
constructor() {
super();
this.rating = 0;
}
connectedCallback() {
const shadowRoot = this.attachShadow({mode: 'open'});
}
}
customElements.define('rating-element', RatingElement);
To use this template element, you query the template, get it's contents, and clone those nodes with templateContent.cloneNode
where the true
argument performs a deep clone. You then initialize the dom with the data.
Congratulations, you now have a Web Component! Unfortunately it does not do anything yet, so next, add some functionality.