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

你有没有想过,能不能像搭积木一样,把网页上的各种功能模块像“零件”一样组装起来?比如一个按钮、一个弹窗、一个搜索框……每个部分都是独立的,你可以自由地复用、组合它们。
这就像是在做乐高玩具,每一块积木都是标准且可重复使用的。
Web Components(网页组件)就是让这件事成为现实的技术。它是浏览器原生支持的一套组件化开发方式,不依赖任何框架(比如Vue、React等),可以直接在HTML、CSS和JavaScript中使用。
它能做什么?
- 创建自定义HTML标签:比如
<my-button>或者<user-card>。 - 封装样式和行为:组件内部的CSS和JS不会影响外部内容。
- 跨项目复用:写好的组件可以被多个项目使用,就像插件一样。
- 与现有技术无缝集成:无论你是使用jQuery、Vue、React还是其他框架,都可以使用Web Components。
总之,它是一种“轻量级、通用、原生”的组件开发方式,是现代前端开发的新趋势。
环境准备:搭建你的第一个Web Components项目

要开始写Web Components,我们只需要最基础的三样东西:
- 一台电脑
- 浏览器(推荐Chrome或Edge)
- 文本编辑器(如 VS Code)
下面我们就一步步来准备环境。
第一步:安装VS Code(代码编辑器)
如果你还没有安装VS Code,请访问官网 https://code.visualstudio.com/ 下载并安装。
安装完成后,打开它,准备开始写代码。
第二步:创建一个简单的HTML项目结构
我们在本地新建一个文件夹,比如叫 web-components-demo,然后在里面创建以下文件结构:
web-components-demo/
├── index.html
└── main.js
编写 index.html 文件内容如下:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<title>我的第一个Web Component</title>
</head>
<body>
<h1>Hello, Web Components!</h1>
<!-- 我们稍后会在这里添加自定义组件 -->
<hello-component></hello-component>
<!-- 引入主 JS 脚本 -->
<script type="module" src="./main.js"></script>
</body>
</html>
注意:这里我们用了 <script type="module">,这是ES模块的标准语法,Web Components通常都需要模块引入方式。
第三步:运行你的HTML文件
现在我们想看到页面效果,但直接双击HTML文件可能因为安全限制无法加载模块脚本。我们可以使用一个简单的方式来运行页面。
方法一:使用VS Code插件 Live Server
- 打开 VS Code。
- 在左侧资源管理器中右键点击
index.html,选择 "Open with Live Server"。 - 页面将在浏览器中自动打开,并正常加载模块脚本。
方法二:手动启动一个本地服务器(适合高级用户)
如果你熟悉命令行,可以用 Python 启动一个简单的HTTP服务:
# Python 3.x
python -m http.server 8000
然后访问 http://localhost:8000 就可以看到你的页面。
到这一步,我们的开发环境就准备好了!
核心概念:理解Web Components的三个核心技术

Web Components 是由三项核心技术组成的,分别是:
- Custom Elements(自定义元素)
- Shadow DOM(影子DOM)
- HTML Templates(模板标签)
下面我用通俗的语言来解释这三个概念。
1. Custom Elements:自定义 HTML 标签
还记得小时候玩的乐高积木吗?每个积木都有自己的形状和颜色。
Custom Elements 就相当于你自己设计了一块专属的积木。你可以用 <my-button> 这样的标签,代替原来的 <button>。
如何创建一个自定义元素?
让我们来写一个最简单的例子。
在 main.js 中添加以下代码:
class HelloComponent extends HTMLElement {
constructor() {
super(); // 必须调用父类构造函数
this.innerHTML = "<p>你好,我是自定义组件!</p>";
}
}
// 注册这个组件,名字必须包含短横线 -
customElements.define("hello-component", HelloComponent);
然后刷新你的页面,你会看到这句话显示出来:
你好,我是自定义组件!
这就是一个最基本的自定义组件。是不是很简单?
2. Shadow DOM:组件之间的样式隔离
如果我们只是用上面的方法创建组件,那它的样式会被全局污染,也就是说,如果我们在外面加一个 <style>,里面写的样式可能会意外影响到组件。
Shadow DOM 的作用就是给组件一个“私有的空间”,让它里面的样式和结构不会受到外界干扰。
给组件加上 Shadow DOM
继续修改 main.js 中的代码:
class HelloComponent extends HTMLElement {
constructor() {
super();
// 创建 Shadow DOM 并附加
const shadow = this.attachShadow({ mode: "open" });
// 创建一段文字内容
const p = document.createElement("p");
p.textContent = "你好,我是 Shadow DOM 里的组件!";
// 添加内联样式,只会影响当前组件
p.style.color = "blue";
// 把内容加入 Shadow DOM
shadow.appendChild(p);
}
}
customElements.define("hello-component", HelloComponent);
刷新页面,你会看到蓝色的文字,而且外面的 CSS 不会影响它,达到了样式隔离的效果。
3. HTML Templates:可复用的模板内容
有时候我们希望为组件写一个比较复杂的结构,每次都靠字符串拼接不是很好维护。
HTML Template 就是用来保存结构的“图纸”,你可以先写好模板,然后在 JavaScript 中反复使用它。
示例:使用 <template> 定义组件结构
修改 index.html:
<template id="hello-template">
<style>
p {
color: green;
font-weight: bold;
}
</style>
<p>这是一个从模板生成的内容!</p>
</template>
然后在 main.js 中读取并应用这个模板:
class HelloComponent extends HTMLElement {
constructor() {
super();
// 获取 template 元素
const template = document.getElementById("hello-template");
// 创建 Shadow DOM
const shadow = this.attachShadow({ mode: "open" });
// 克隆模板内容并添加进组件
const instance = template.content.cloneNode(true);
shadow.appendChild(instance);
}
}
customElements.define("hello-component", HelloComponent);
刷新页面,你会看到绿色加粗的文字,说明模板成功应用了!
实战项目:制作一个“卡片组件”


为了巩固前面的知识,我们现在来做一个小项目:用户信息卡片组件。
这个组件将会显示用户的头像、姓名、简介等内容,是一个典型的“UI组件”。
步骤 1:写出模板结构
修改 index.html,添加如下 <template>:
<template id="user-card">
<style>
.card {
border: 1px solid #ccc;
padding: 16px;
max-width: 300px;
margin: 16px;
border-radius: 8px;
box-shadow: 0 2px 5px rgba(0,0,0,0.1);
font-family: sans-serif;
}
img {
width: 100px;
height: 100px;
border-radius: 50%;
}
</style>
<div class="card">
<img src="https://via.placeholder.com/100" alt="用户头像" />
<h2>张三</h2>
<p>软件工程师</p>
</div>
</template>
步骤 2:创建组件类并注册
修改 main.js:
class UserCardComponent extends HTMLElement {
constructor() {
super();
const template = document.getElementById("user-card");
const shadow = this.attachShadow({ mode: "open" });
const instance = template.content.cloneNode(true);
shadow.appendChild(instance);
}
}
customElements.define("user-card", UserCardComponent);
步骤 3:在页面中使用组件
回到 index.html,在任意位置插入这个标签:
<user-card></user-card>
刷新页面,你应该能看到一个漂亮的用户卡片出现了!
拓展一下:让卡片支持传参(属性传递)
目前这个卡片是固定的“张三”,那我们能不能让它接受不同用户的信息呢?
我们可以利用组件的属性来实现动态数据绑定。
修改模板中的HTML结构
将之前的 <h2>张三</h2> 和 <p>软件工程师</p> 改成占位符形式:
<h2 id="name">用户名字</h2>
<p id="job">职业信息</p>
修改 main.js 来读取组件的属性
class UserCardComponent extends HTMLElement {
constructor() {
super();
const template = document.getElementById("user-card");
const shadow = this.attachShadow({ mode: "open" });
const instance = template.content.cloneNode(true);
shadow.appendChild(instance);
// 读取组件上的属性
const name = this.getAttribute("name") || "默认名字";
const job = this.getAttribute("job") || "未知职业";
// 获取模板中对应的元素,并设置内容
const nameEl = instance.querySelector("#name");
const jobEl = instance.querySelector("#job");
if (nameEl) nameEl.textContent = name;
if (jobEl) jobEl.textContent = job;
}
}
customElements.define("user-card", UserCardComponent);
使用时传入参数
修改 index.html 中的使用方式:
<user-card name="李四" job="产品经理"></user-card>
<user-card name="王五" job="设计师"></user-card>
刷新页面,你会看到两个不同的卡片分别显示了李四和王五的信息!
这样我们就完成了一个可以动态传值、样式隔离、结构复用的组件!
常见问题解答:新手最容易卡住的地方
✨ Q1:为什么我的组件没有显示出来?
常见原因:
- 没有注册组件:忘记调用
customElements.define(...)。 - 自定义标签名不符合规范:必须至少包含一个短横线
-,如my-component。 - 没有使用
<script type="module">加载脚本。 - 模板克隆失败:确保 ID 正确、模板存在。
✨ Q2:如何调试 Web Components?
- 使用浏览器开发者工具(F12),查看是否成功注册组件。
- 查看控制台是否有报错信息。
- 右键点击组件,选择“检查”查看 Shadow DOM 内容是否正确。
✨ Q3:Shadow DOM 中不能直接操作 DOM?
你可以通过 querySelector()、querySelectorAll() 等方法获取和操作 Shadow DOM 中的元素。
例如:
const shadow = this.attachShadow({ mode: 'open' });
shadow.innerHTML = '<div id="myDiv">Hello</div>';
const myDiv = shadow.getElementById('myDiv');
学习建议:接下来该学什么?
恭喜你完成了第一个 Web Component 的开发!接下来你可以沿着这些方向继续深入学习:
📚 进阶知识点推荐:
| 主题 | 内容 |
|---|---|
| 生命周期回调 | connectedCallback、disconnectedCallback 等 |
| 观察属性变化 | 使用 observedAttributes 和 attributeChangedCallback |
| 插槽(Slot) | 支持向组件内插入自定义内容 |
| 构建可复用库 | 将组件打包成 npm 包供他人使用 |
| 与框架集成 | 如何在 Vue/React 中使用 Web Components |
📌 推荐学习顺序:
- 掌握基本的 Custom Element 写法
- 熟练使用 Shadow DOM 和 Template
- 理解组件通信机制(属性 vs 事件)
- 学会用 Slots 提供更灵活的内容插入能力
- 了解组件生命周期和状态管理
- 学习如何发布和共享组件(如通过 npm)
结语
通过这篇教程,你已经掌握了 Web Components 最核心的基础知识,并完成了一个可以复用的组件示例。
虽然这只是 Web Components 的冰山一角,但你已经站在了通往组件化编程的大门口。
记住一句话:
“组件化的本质,是把复杂的事情拆分成一个个小而确定的部分。”
Web Components 就是这样一个帮助你构建清晰、可维护、可扩展项目的利器。
继续加油吧,未来的前端高手!
🎉 附录:完整源码地址(参考)
你可以在这个 GitHub 地址查看完整的项目代码:
https://github.com/example/web-components-tutorial
(请自行替换为你真实的项目仓库地址)
🌟 有问题欢迎在评论区留言或发送邮件给我
📧 邮箱:teacher@example.com
💬 微信社群:Web前端新手成长营
祝你 coding 快乐,早日成为全栈工程师!💪

评论 0