Web Components:原生组件化开发新趋势 —— 面向零基础初学者的教程
一、开篇:什么是Web Components?它能用来做什么?

你有没有想过,为什么在网页上看到一个按钮或输入框时,它们看起来都差不多,但背后却可能来自不同的框架?这是因为这些界面元素通常由HTML标签直接提供,比如 <button> 和 <input>。
那如果我们想创造属于自己的 HTML 标签呢?例如写一个 <my-calendar> 或 <custom-header> 呢?这听起来像是天马行空的想法,但现实是:可以实现!而且不用任何框架(Vue、React等)也能做到。
这就是我们今天要讲的内容:Web Components(网络组件)。
Web Components 是什么?
简单来说:
Web Components 就是一组浏览器原生支持的技术标准,允许你创建可复用、自定义的 HTML 元素。
它可以让你像编写普通 HTML 标签一样使用自己的组件。就像下面这样:
<my-counter></my-counter>
无需借助 Vue 或 React,只需要标准的 HTML/CSS/JS 就可以完成这个组件的定义和使用。
Web Components 有什么用?
- ✅ 创建“自己定义”的 HTML 元素(如
<tabs>、<notification-box>等) - 🔄 组件高度封装、可复用
- 🔌 与任何前端框架兼容甚至无缝集成
- 🧠 原生支持,无需依赖第三方库
二、环境准备:你需要做的第一步

作为初学者,不需要安装复杂的编辑器或框架,只要准备好最基础的工具即可:
所需工具清单:
- 一台电脑(Windows/Mac/Linux都可以)
- 任意文本编辑器:
- 推荐:VS Code(免费、功能强大)
- 任意现代浏览器:
- Chrome / Edge / Firefox / Safari 都支持 Web Components
项目结构建议(用于练习)
你可以建立如下简单的文件夹结构来开始学习:
web-components-demo/
│
├── index.html
├── main.js
└── style.css
示例代码初始化
打开 index.html 输入以下内容:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<title>Web Components 学习</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<h1>欢迎来到 Web Components 教程</h1>
<!-- 待会我们将在这里放我们的自定义组件 -->
<script src="main.js" type="module"></script>
</body>
</html>
注意:我们使用了 type="module" 来引入 JS 模块,这是 Web Components 必须的基础。
三、核心概念详解(带代码示例)

Web Components 包括三项核心技术:
- 自定义元素(Custom Elements)
- Shadow DOM(影子DOM)
- HTML模板(Templates)
我们逐一讲解,并结合实例进行说明。
3.1 自定义元素(Custom Element)
我们可以使用 JavaScript 的 customElements.define() 方法来创建自己的 HTML 标签。
示例:创建一个叫 <hello-world> 的自定义标签
在 main.js 中添加以下代码:
class HelloWorld extends HTMLElement {
constructor() {
super();
this.innerText = "Hello, 自定义组件!";
}
}
customElements.define("hello-world", HelloWorld);
现在回到你的 HTML 文件中加入这个标签:
<hello-world></hello-world>
刷新页面看看效果吧!
💡 新手提醒:
- 类名必须以大写字母开头。
- 调用
super()是为了继承基本行为。 - 元素名必须包含短横线(-),不能只是一个单词,比如
card不合法,要用my-card。
3.2 使用 Shadow DOM 实现样式隔离
默认情况下,我们在主页面中的 CSS 可能会影响到自定义组件中的样式。为了让组件有更独立的样式空间,我们可以用 Shadow DOM。
示例:给 <hello-world> 加入 Shadow DOM
修改 main.js 如下:
class HelloWorld extends HTMLElement {
constructor() {
super();
// 创建 Shadow Root
const shadow = this.attachShadow({ mode: 'open' });
// 创建一个 span 并插入到 Shadow DOM 中
const span = document.createElement('span');
span.textContent = "Hello from Shadow DOM!";
span.style.color = "blue";
shadow.appendChild(span);
}
}
customElements.define("hello-world", HelloWorld);
此时,你在主页面写的外部 CSS 不会影响该组件内的样式!
✅ 总结一下 Shadow DOM 的优点:
- 组件样式完全隔离
- 避免 CSS 冲突
- 更容易维护复杂项目
3.3 HTML Template 模板复用
如果我们要展示比较复杂的 HTML 结构,每次都通过 JS 动态创建节点就太麻烦了。这时候我们就可以用 <template> 标签来提前准备好结构。
示例:创建一个卡片组件 <user-card>
在 index.html 中添加:
<template id="user-card-template">
<style>
.card {
border: 1px solid #ccc;
padding: 10px;
margin: 10px 0;
max-width: 300px;
}
h2 { color: darkorange; }
</style>
<div class="card">
<h2>用户名:李小明</h2>
<p>用户年龄:25岁</p>
</div>
</template>
然后在 main.js 中编写对应的组件类:
class UserCard extends HTMLElement {
constructor() {
super();
const template = document.getElementById("user-card-template");
const shadow = this.attachShadow({ mode: 'open' });
shadow.appendChild(template.content.cloneNode(true));
}
}
customElements.define("user-card", UserCard);
最后,在 HTML 页面中插入:
<user-card></user-card>
你就能看到一个完整风格的用户信息卡!
四、实战项目:做一个点击计数器组件 <click-counter>

让我们动手来做一个完整的组件实践。
目标:每次点击按钮,数字 +1,显示在一个自定义元素中。
第一步:添加模板结构
在 index.html 中添加:
<template id="counter-template">
<style>
button {
font-size: 16px;
padding: 10px;
cursor: pointer;
}
p {
font-weight: bold;
}
</style>
<button>点击我</button>
<p>点击次数:<span>0</span></p>
</template>
第二步:定义组件逻辑
在 main.js 中添加:
class ClickCounter extends HTMLElement {
constructor() {
super();
const template = document.getElementById("counter-template");
const shadow = this.attachShadow({ mode: 'open' });
const clone = template.content.cloneNode(true);
this.shadowRoot = shadow;
shadow.appendChild(clone);
// 获取按钮和计数器 span
this.button = shadow.querySelector("button");
this.countSpan = shadow.querySelector("span");
this.count = 0;
// 添加点击事件
this.button.addEventListener("click", () => {
this.count++;
this.countSpan.textContent = this.count;
});
}
}
customElements.define("click-counter", ClickCounter);
第三步:使用组件
在 HTML 中插入:
<click-counter></click-counter>
保存所有文件并刷新浏览器,你会看到一个可点击的计数器!
五、常见问题解答(FAQ)
问:Web Components 和 Vue/React 有什么区别?
答:
- Vue/React 是成熟的框架,功能丰富,生态成熟;
- Web Components 是浏览器原生特性,适合组件级别封装,不绑定于某一个技术栈;
- Web Components 可以被任意框架使用,也可以与传统 HTML 结合。
问:为什么不推荐全局 CSS 影响我的组件?
答:
因为如果你的组件样式被其他页面影响了,那就不是真正的组件化。Shadow DOM 提供了样式隔离,保证了组件的健壮性和可移植性。
问:为什么自定义元素名称需要带短横线?
答:
这是一个规范(来自 WHATWG)。目的是避免未来与标准 HTML 元素冲突。例如,未来可能会出现 dialog 或 menu 这样的官方标签,而不会和我们自定义的名字重复。
问:能否将 Web Components 应用在旧浏览器中?
答:
主流现代浏览器(Chrome、Edge、Firefox、Safari)都已支持 Web Components,但对于 IE11 或更低版本浏览器,需要引入 polyfill 补丁。
六、下一步学习建议
恭喜你完成了第一个 Web Components 项目的构建!下面是一些进阶方向:
建议 1:掌握属性和事件传递
尝试让组件接受外部传入的数据:
<click-counter initial-count="5"></click-counter>
可以通过 attributeChangedCallback() 监听属性变化。
建议 2:了解自定义元素生命周期方法
常用的钩子函数包括:
| 方法 | 描述 |
|---|---|
constructor() |
构造函数,最先执行 |
connectedCallback() |
当组件插入页面时触发 |
disconnectedCallback() |
移除组件时触发 |
adoptedCallback() |
在文档之间移动时调用 |
attributeChangedCallback() |
属性变化监听 |
建议 3:配合现有框架使用
虽然 Web Components 可以单独使用,但它也可以很好融入 Vue、React、Angular 等框架中。
例如在 React 中使用只需:
function App() {
return (
<div>
<click-counter initial-count="10"></click-counter>
</div>
)
}
记得在入口文件中加载 Web Components!
建议 4:阅读文档和社区资源
- 官方 MDN 文档:MDN Web Components
- Google 开发者指南:Web Component Best Practices
- 社区仓库:Open WC
总结
通过本教程,你学会了:
- 什么是 Web Components
- 如何搭建开发环境
- 核心三大技术(自定义元素、Shadow DOM、Template)
- 完成了一个点击计数器组件的实战
- 解决了初学者常遇到的问题
你现在已经掌握了浏览器原生的组件开发方式,可以尝试创建更多实用的自定义组件,甚至发布分享给他人使用!
继续加油,成为真正懂“底层原理”的全栈开发者吧!🚀
如果你喜欢这份教程,请点赞、收藏并分享给其他正在学习编程的朋友。也欢迎留言告诉我你想看哪些前端相关的后续内容!

评论 0