-
-
Save exside/dc072926e8ac6062b98690e5e84d1abe to your computer and use it in GitHub Desktop.
My annotated copy of https://gist.github.com/kristoferjoseph/c4e47389ae0f0447db175b914e471628
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<meta charset="UTF-8" /> | |
<title>Single File Web Component</title> | |
<style> | |
body { | |
background-color: #eee; | |
font-family: Helvetica, sans-serif; | |
} | |
h1 { | |
color: blue; | |
background-color: pink; | |
} | |
</style> | |
</head> | |
<body> | |
<template id="single-file"> | |
<style> | |
/* | |
These styles affect only content inside the shadow DOM. | |
Styles in the outside document mostly do not affect these, | |
with the exception of inheritable styles such as color, | |
font and line-height. | |
*/ | |
h1 { | |
color: red; | |
} | |
</style> | |
<h1>Hello world (web component)</h1> | |
<!-- | |
This code still works if you remove the type="module" parameter. | |
Using that parameter enables features such as 'import ... from' | |
More importantly it stops variables inside the script tag from | |
leaking out to the global scope - if you remove type="module" | |
from here then the HelloWorld class becomes visible. | |
--> | |
<script type="module"> | |
class HelloWorld extends HTMLElement { | |
constructor() { | |
/* | |
If you remove the call to super() here Firefox shows an error: | |
"Uncaught ReferenceError: must call super constructor before | |
using 'this' in derived class constructor'" | |
*/ | |
super(); | |
const template = document.getElementById("single-file"); | |
/* | |
mode: 'open' means you are allowed to access | |
document.querySelector('hello-world').shadowRoot to get | |
at the DOM inside. Set to 'closed' and the .shadowRoot | |
property will return null. | |
*/ | |
this.attachShadow({ mode: "open" }).appendChild( | |
template.content.cloneNode(true) | |
); | |
/* | |
template.content is a 'DocumentFragment' array. | |
template.content.cloneNode() without the true performs | |
a shallow clone, which provides a empty DocumentFragment | |
array. | |
template.content.cloneNode(true) provides one with 6 items | |
*/ | |
} | |
connectedCallback() { | |
// https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_custom_elements#using_the_lifecycle_callbacks | |
console.log("Why hello there 👋"); | |
} | |
} | |
customElements.define("hello-world", HelloWorld); | |
</script> | |
</template> | |
<h1>This is not a web component</h1> | |
<hello-world></hello-world> | |
<script> | |
const sf = document.getElementById("single-file"); | |
/* | |
Before executing this line, sf.content.lastElementChild | |
is the <script type="module"> element hidden away inside | |
the <template> - we remove it from the template here and | |
append it to the document.body, causing it to execute in | |
the main document and activate the <hello-world> tag. | |
*/ | |
document.body.appendChild(sf.content.lastElementChild); | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment