Web Components:原生组件化开发新趋势
开篇:Web Components 究竟是什么?

在现代网页开发中,我们经常听说“组件化开发”,这指的是将网页的不同部分拆分成一个个独立、可复用的“组件”。而Web Components,就是浏览器原生支持的一种组件化技术。它不需要你使用任何框架(比如 React 或 Vue),就能让你创建出像搭积木一样的 HTML 标签。
为什么要学 Web Components?
- 原生支持:所有主流浏览器都支持 Web Components。
- 不依赖框架:即使你不会 React、Vue 或 Angular,也能写出模块化的网页。
- 跨项目复用性强:写好的组件可以在任何网站中直接使用。
- 学习成本低:只要你会基础的 HTML、CSS 和 JavaScript,就能上手。
这篇文章会从零开始带你一步步入门 Web Components,并通过一个实战项目来加深理解。
环境准备:轻松搭建你的开发环境

要开始使用 Web Components,你需要的是最基本的前端开发工具:
所需工具:
- 文本编辑器(推荐 VS Code)
- 浏览器(推荐 Chrome 或 Edge)
- 本地服务器(可选)
具体步骤:
第一步:安装 VS Code
前往官网下载并安装 Visual Studio Code:
👉 https://code.visualstudio.com/
安装完成后,打开它,这就是我们今后写代码的地方。
第二步:创建项目文件夹
在电脑上新建一个文件夹,比如命名为 web-components-tutorial,然后在 VS Code 中打开这个文件夹。
第三步:创建三个基础文件
在这个文件夹里创建三个文件:
index.html—— 页面结构style.css—— 样式文件main.js—— 主要逻辑和组件定义
第四步:设置本地服务器(可选但推荐)
直接打开 index.html 文件可能会遇到一些安全限制,因此建议你使用一个简单的本地服务器。
你可以使用以下几种方式:
- 安装 VS Code 插件 Live Server,右键点击
index.html→ Open with Live Server - 如果你会 Node.js,可以用:
npx serve
现在,开发环境已经准备好!
核心概念:Web Components 的三大支柱

Web Components 由三项核心技术组成:
| 技术名称 | 功能说明 |
|---|---|
| 自定义元素 | 创建新的 HTML 标签 |
| Shadow DOM | 为组件添加隔离的样式和结构 |
| HTML 模板 | 定义组件的内容模板,提高复用性 |
我们一个一个来看。
一、自定义元素(Custom Elements)
这是 Web Components 最核心的部分 —— 你可以创建自己的 HTML 标签,比如 <my-button>,然后像普通标签一样使用它。
示例:创建一个简单的按钮组件
<!-- index.html -->
<my-button>点我呀</my-button>
// main.js
class MyButton extends HTMLElement {
constructor() {
super();
// 给按钮加一个 click 事件
this.addEventListener('click', () => {
alert('按钮被点击了!');
});
}
}
customElements.define('my-button', MyButton);
这样,你就创建了一个可以复用的自定义按钮组件。它不仅能响应点击事件,还可以在任意 HTML 文件中直接使用。
💡 小贴士:
HTML 标签名必须包含短横线(例如 my-button),这是规范要求,防止和未来标准标签冲突。
二、Shadow DOM(影子 DOM)
当你开发组件时,希望它的样式不会影响页面其他部分,也不会被外部 CSS 干扰 —— 这时候就要用到 Shadow DOM。
Shadow DOM 就像给组件穿了一层“保护膜”,让它的内部结构和样式与外界隔离。
示例:带样式的按钮组件
class MyStyledButton extends HTMLElement {
constructor() {
super();
// 创建 shadow root
const shadow = this.attachShadow({ mode: 'open' });
// 创建一个 <button> 元素
const button = document.createElement('button');
button.textContent = this.getAttribute('label') || '默认按钮';
button.style.backgroundColor = 'skyblue';
button.style.padding = '10px 20px';
button.style.borderRadius = '5px';
// 添加点击事件
button.addEventListener('click', () => {
alert('带样式的按钮被点击了!');
});
// 把按钮加入 shadow DOM
shadow.appendChild(button);
}
}
customElements.define('my-styled-button', MyStyledButton);
<!-- index.html -->
<my-styled-button label="蓝色按钮"></my-styled-button>
运行后你会发现按钮变成了蓝色,并且无论你在外部写什么样的样式,都不会影响它。
三、HTML 模板(Template)
如果你需要更复杂的组件内容,可以使用 <template> 标签预先定义好结构,然后在 JS 中克隆使用。
示例:使用模板创建卡片组件
<!-- index.html -->
<template id="card-template">
<style>
.card {
border: 1px solid #ccc;
padding: 1rem;
margin: 1rem;
width: 200px;
box-shadow: 2px 2px 8px rgba(0,0,0,0.1);
}
h3 {
color: #333;
}
p {
font-size: 14px;
}
</style>
<div class="card">
<h3>标题</h3>
<p>这里是描述文字</p>
</div>
</template>
<my-card title="介绍" description="这是一个基于 template 的卡片组件"></my-card>
// main.js
class MyCard extends HTMLElement {
constructor() {
super();
const template = document.getElementById('card-template').content;
const shadow = this.attachShadow({ mode: 'open' });
// 克隆模板内容
const clone = template.cloneNode(true);
// 修改内容
const titleEl = clone.querySelector('h3');
const descEl = clone.querySelector('p');
titleEl.textContent = this.getAttribute('title');
descEl.textContent = this.getAttribute('description');
// 插入到组件中
shadow.appendChild(clone);
}
}
customElements.define('my-card', MyCard);
运行之后,你会看到一张漂亮的卡片组件,而且样式完全隔离。
实战项目:制作一个“待办事项”组件
接下来我们将综合运用前面的知识,实现一个小型的待办事项组件 <todo-list>。
功能需求:
- 显示一个输入框和一个添加按钮
- 输入任务内容后,点击按钮新增一条待办项
- 点击已完成的任务可以打勾标记完成
步骤一:创建组件结构
<!-- index.html -->
<template id="todo-template">
<style>
:host {
display: block;
max-width: 400px;
margin: 20px auto;
}
input[type="text"] {
padding: 6px 10px;
width: 70%;
font-size: 16px;
}
button {
padding: 6px 12px;
font-size: 16px;
}
ul {
list-style: none;
padding-left: 0;
margin-top: 10px;
}
li {
padding: 6px;
margin-bottom: 5px;
background-color: #f0f0f0;
cursor: pointer;
}
li.done {
text-decoration: line-through;
opacity: 0.6;
}
</style>

<input type="text" placeholder="输入任务..." />
<button>添加</button>
<ul></ul>
</template>
<todo-list></todo-list>
步骤二:编写 JS 逻辑
class TodoList extends HTMLElement {
constructor() {
super();
const template = document.getElementById('todo-template').content;
const shadow = this.attachShadow({ mode: 'open' });
const clone = template.cloneNode(true);
shadow.appendChild(clone);
const input = shadow.querySelector('input');
const button = shadow.querySelector('button');
const ul = shadow.querySelector('ul');
function createTodoItem(text) {
const li = document.createElement('li');
li.textContent = text;
li.addEventListener('click', () => {
li.classList.toggle('done');
});
return li;
}
button.addEventListener('click', () => {
const text = input.value.trim();
if (text !== '') {
const item = createTodoItem(text);
ul.appendChild(item);
input.value = '';
}
});
}
}
customElements.define('todo-list', TodoList);
刷新页面后,你应该能看到一个完整的待办事项组件,可以添加、删除和标记完成任务!
常见问题解答
Q1:为什么我的组件样式没有生效?
可能是因为你忘记把样式放进 shadow DOM 中,或者样式选择器有问题。确保每个组件都有自己的 <style> 标签,并且使用正确的类名或属性选择器。
Q2:为什么不能直接使用 React/Vue 风格的写法?
Web Components 是纯原生的技术,和框架无关,所以语法和理念略有不同。但正因为如此,它更适合用来构建高度可复用的基础组件库。
Q3:如何调试 Web Components?
使用浏览器开发者工具(F12)查看 shadow DOM 内容,检查节点和样式是否正确插入即可。
学习建议:下一步怎么学?
学完这篇教程后,你已经掌握了 Web Components 的基本技能。下面是一些进阶方向,帮助你走得更远:
1. 深入学习 Custom Elements API
- 使用
observedAttributes观察属性变化 - 在
connectedCallback()和disconnectedCallback()中处理组件生命周期
2. 结合 Lit.js / FAST 等轻量框架
这些是专门为 Web Components 设计的辅助库,能让你更高效地开发组件,比如支持模板绑定、响应式更新等。
3. 创建组件库
尝试把自己常用的组件打包成一套 UI 库,发布到 npm,供他人调用。
4. 参考官方文档和社区资源
- MDN 文档:https://developer.mozilla.org/zh-CN/docs/Web/API/Web_Components
- W3C 官方规范:https://www.w3.org/standards/techs/webcomponents#w3c_all
总结

通过本教程,你学会了:
✅ 如何创建自定义 HTML 标签
✅ 如何使用 Shadow DOM 实现样式隔离
✅ 如何使用 Template 创建复杂组件结构
✅ 实现了一个实用的待办事项组件
✅ 解决了一些常见疑问
继续练习是掌握 Web Components 的关键。试着自己动手改一改今天写的组件,或者做一个新的组件,比如“计数器按钮”、“颜色选择器”等,你会发现 Web Components 是一种非常强大又灵活的开发方式!
祝你学习愉快,欢迎持续深入探索 Web 开发的新世界!

评论 0