Introduction to Web Components: History, Concepts, Custom Elements, Shadow DOM, Template and Slot
This article provides a comprehensive overview of Web Components, covering their development timeline, core concepts such as Custom Elements, Shadow DOM, templates and slots, practical code examples, lifecycle callbacks, debugging tools, and real‑world usage scenarios for modern frontend development.
Introduction
The article aims to help readers understand what Web Components are, offering a concise demonstration rather than a full tutorial.
Development History
2011 – Google starts the Polymer project.
2013 – W3C begins standardizing Custom Elements, HTML Templates, and Shadow DOM.
2015 – Web Components 1.0 draft released.
2017 – Web Components 1.0 becomes an official standard.
2018 – Chrome 63 adds full support.
2019 – Wider adoption among frontend developers.
Who Is Using Web Components
YouTube
GitHub
Quark‑Design (Harro)
Vue (supports Web Components)
Goal
To give a brief introduction to Web Components and provide simple examples for quick learning.
Basic Concepts
Web Components are a set of technologies that enable the creation of reusable, encapsulated custom elements.
They consist of three main parts: Custom Elements, Shadow DOM, and HTML Templates.
Custom Elements
Concept
Custom Elements are HTML elements defined by developers that extend the browser's native element set.
Implementation
Extend a built‑in element, e.g., HTMLParagraphElement .
Extend the generic HTMLElement base class.
Example
The following example defines a word-count element that counts words inside its parent paragraph.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<div>
<article contenteditable="">
<p>my name is a du</p>
<p is="word-count"></p>
</article>
</div>
<script>
class WordCount extends HTMLParagraphElement {
constructor() {
super();
var wcParent = this.parentNode;
var shadow = this.attachShadow({ mode: "open" });
var count = "Words: " + countWords(wcParent);
var text = document.createElement("span");
text.textContent = count;
shadow.appendChild(text);
setInterval(function() {
var count = "Words: " + countWords(wcParent);
text.textContent = count;
}, 200);
function countWords(node) {
var text = node.innerText || node.textContent;
return text.split(/\s+/g).length;
}
}
}
customElements.define("word-count", WordCount, { extends: "p" });
</script>
</body>
</html>Lifecycle
Custom elements support callbacks such as connectedCallback and disconnectedCallback , which are demonstrated by adding a delete button and logging actions.
Shadow DOM
Concept
Shadow DOM provides a separate DOM tree attached to an element, isolating its markup, style, and behavior from the main document.
Setup
Enable Shadow DOM inspection in the browser (e.g., Chrome DevTools → Preferences → Elements → Show user agent shadow DOM).
Example
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<div id="host"></div>
<span>我是普通dom</span>
<script>
const host = document.querySelector("#host");
const shadow = host.attachShadow({ mode: "open" });
const span = document.createElement("span");
span.textContent = "我是shadow dom";
shadow.appendChild(span);
</script>
</body>
</html>When mode is "open" , JavaScript can access the shadow tree via shadowRoot ; with "closed" , shadowRoot returns null .
CSS Encapsulation
Adding a style block inside the shadow root demonstrates that styles defined there do not leak out to the main page.
<style>
span { color: blue; border: 1px solid black; }
</style>Template and Slot
Template
The <template> element stores markup that is not rendered until instantiated via JavaScript.
Slot
Slots allow developers to define placeholders inside a shadow DOM that can be filled with external content, similar to Vue's slot mechanism.
Example
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<template id="templateId">
<slot name="element-name">插槽的默认值</slot>
</template>
<element-test></element-test>
<element-test>
<span slot="element-name">测试值</span>
</element-test>
<script>
customElements.define(
"element-test",
class extends HTMLElement {
constructor() {
super();
const template = document.getElementById("templateId").content;
const shadowRoot = this.attachShadow({ mode: "open" }).appendChild(template.cloneNode(true));
}
}
);
</script>
</body>
</html>Debugging
Tools similar to Vue DevTools can inspect custom elements, showing properties, attributes, and methods in the Inspector tab and source code in the Source tab.
Practical Applications
Adding custom headers (e.g., token) to image requests.
Testing and adjusting placeholder styles when default browser styles are disabled.
Understanding framework configurations (e.g., Qiankun) by recognizing how Shadow DOM influences component isolation.
Rare Earth Juejin Tech Community
Juejin, a tech community that helps developers grow.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.