Web Components:原生组件化开发新趋势(零基础入门教程)
开篇:Web Components 是什么,能用来做什么?

作为一名刚开始学习前端的小伙伴,你可能已经听说过 Vue、React 或 Angular 这样的框架。它们都有一个共同点:组件化开发。也就是说,把网页的一部分(比如一个按钮、一个导航栏、一个表单)封装成“组件”,方便我们复用和维护。
但今天我们要讲的 Web Components(网页组件),不是某个框架的专属功能,而是浏览器本身就支持的一套技术标准。你可以把它理解为:浏览器官方提供的组件化方式。
🌟 Web Components 能做什么?
- 创建 可复用的 UI 组件
- 不依赖任何框架(如 React、Vue)
- 在不同的项目中直接使用
- 实现真正的 封装性 和 模块化
举个例子:如果你写了一个漂亮的自定义按钮组件,它可以在你的 HTML 页面中像 <div> 一样使用,比如:
<my-fancy-button>点击我</my-fancy-button>
是不是很酷?而且这完全是原生的!
环境准备:搭建开发环境

既然是零基础,我们就从最简单的开始。
✅ 步骤 1:安装代码编辑器
推荐使用免费且强大的编辑器:
- Visual Studio Code(简称 VS Code)
下载安装后,我们就可以开始了。
✅ 步骤 2:创建一个基本的 HTML 文件夹结构
在电脑上新建一个文件夹,例如叫 web-components-demo,然后在里面创建以下两个文件:
✅ index.html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>我的第一个 Web Component 示例</title>
</head>
<body>
<h1>Hello, Web Components!</h1>
<!-- 我们将在这里插入组件 -->
<my-hello-world></my-hello-world>
<script type="module" src="./hello.js"></script>
</body>
</html>
✅ hello.js
// 定义一个类,继承 HTMLElement
class MyHelloWorld extends HTMLElement {
constructor() {
super();
// 创建一个 Shadow DOM
const shadow = this.attachShadow({ mode: 'open' });
// 创建内容
const div = document.createElement('div');
div.textContent = '你好,我是 Web Component!';
div.style.color = 'blue';
// 把内容添加进 Shadow DOM
shadow.appendChild(div);
}
}
// 注册组件标签名
customElements.define('my-hello-world', MyHelloWorld);
✅ 步骤 3:在浏览器中运行
你需要通过本地服务器打开这个 HTML 文件,不能直接双击打开,否则会因为安全策略报错。
有两种简单的方法:
方法一:使用 VS Code + Live Server 插件
- 在 VS Code 中打开该文件夹。
- 安装插件 Live Server(搜索并安装)。
- 右键点击
index.html,选择 “Open with Live Server”。
浏览器就会自动打开页面了。
方法二:使用 Python 启动简易服务器
如果你有安装 Python,可以在终端运行:
cd web-components-demo
python -m http.server 8000
然后访问地址:http://localhost:8000/index.html
核心概念:通俗讲解关键知识点
Web Components 的核心由三个部分组成:
- Custom Elements(自定义元素)
- Shadow DOM(影子 DOM)
- HTML Templates(HTML 模板)
下面我们分别解释这些“听起来很高大上”的东西,其实都很简单。
1️⃣ Custom Elements(自定义元素)
这是 Web Components 的核心功能之一。你可以像写 HTML 标签一样写自己的组件。
就像这样:
<my-awesome-button>提交</my-awesome-button>
如何做到?很简单:
- 创建一个类,继承
HTMLElement - 用
customElements.define()注册这个类对应的标签名
回顾前面的代码:
class MyHelloWorld extends HTMLElement { ... }
customElements.define('my-hello-world', MyHelloWorld);
⚠️ 注意事项:
- 自定义标签名必须包含短横线(
-),比如my-hello-world,不能是mycomponent。 - 必须使用
type="module"来引入脚本。
2️⃣ Shadow DOM(影子 DOM)
Shadow DOM 就像是组件的一个“隔离区域”。你可以在这个区域里写 HTML 和 CSS,它们不会影响到页面的其他部分。
为什么需要 Shadow DOM?
想象一下,如果你在一个组件中用了 .btn 类名,而整个网页其他地方也有 .btn,会不会互相干扰?CSS 冲突怎么办?
用了 Shadow DOM,每个组件的样式就是独立的,不会再乱跑啦!
怎么创建?
很简单,在组件中加上:
const shadow = this.attachShadow({ mode: 'open' });
然后向这个 shadow 对象中插入 HTML 元素即可。
3️⃣ HTML Templates(HTML 模板)
如果我们想让组件的 HTML 结构复杂一点,直接用 JavaScript 创建节点会很麻烦。
这时候我们可以先写好一个 HTML 片段模板,再复制进来。
💡 示例:
<template id="hello-template">
<style>
.box {
padding: 10px;
background-color: lightgray;
}
</style>
<div class="box">这是一个带有样式的组件</div>
</template>
然后在 JS 中使用:
const template = document.getElementById('hello-template').content;
const shadow = this.attachShadow({ mode: 'open' });
shadow.appendChild(template.cloneNode(true));
这样就能轻松地在组件中加入复杂的 HTML 和样式了。
📌 小总结
| 名称 | 功能 | 关键词 |
|---|---|---|
| Custom Elements | 定义自己的 HTML 标签 | class, define() |
| Shadow DOM | 隔离组件的 HTML 和 CSS | attachShadow() |
| HTML Templates | 定义组件的 HTML 结构 | <template> |

实战项目:跟着教程一步步完成一个组件
接下来,我们来做一个实战项目 —— 创建一个 带关闭按钮的卡片组件。
🛠 功能需求:
- 显示一段内容
- 有一个关闭按钮,点击可以隐藏组件
第一步:HTML 模板准备
修改 index.html,加入如下模板:
<template id="card-template">
<style>
.card {
border: 1px solid #ccc;
padding: 15px;
max-width: 300px;
margin-bottom: 10px;
position: relative;
}
.close-btn {
position: absolute;
top: 5px;
right: 10px;
cursor: pointer;
color: red;
}
</style>
<div class="card">
<span class="close-btn">×</span>
<slot><p>默认内容</p></slot>
</div>
</template>
这里有个新朋友:<slot>,它是 Web Components 的插槽机制。作用是允许你在使用组件时传入自己的内容。
第二步:JS 文件配置
替换或修改 card.js 文件:
class MyCard extends HTMLElement {
constructor() {
super();
// 获取模板内容
const template = document.getElementById('card-template').content;
// 创建 Shadow DOM
const shadow = this.attachShadow({ mode: 'open' });
// 克隆模板内容并插入
const clone = template.cloneNode(true);
// 找到关闭按钮
const closeBtn = clone.querySelector('.close-btn');
// 设置点击事件
closeBtn.addEventListener('click', () => {
this.remove(); // 删除自己
});
shadow.appendChild(clone);
}
}
customElements.define('my-card', MyCard);
第三步:使用组件
在 index.html 中使用这个组件:
<my-card>
<p>我是动态内容!</p>
</my-card>
刷新浏览器,你会看到一个带有 × 按钮的卡片,点击 × 就会消失!
💡 提示:多插几个试试看
你可以这样多次使用它:
<my-card>内容1</my-card>
<my-card>内容2</my-card>
<my-card>内容3</my-card>
效果会全部展示出来,并且每个都能单独关闭。
常见问题解答
作为初学者,可能会遇到一些疑问,我们来一起解决。
❓Q1:注册组件时提示 Cannot redefine custom element
可能是你重复注册了同一个标签名,比如不小心写了两次 customElements.define('my-card', ...)。
✅ 解决方法:
确保每次只注册一次,或者在浏览器刷新后再试。
❓Q2:我的组件不显示?
检查以下几点:
- 标签名是否正确(有没有
-) - JS 是否被正确加载(控制台有无错误)
type="module"是否写对- 使用了
attachShadow吗? - 浏览器是否支持 Web Components(现代浏览器都支持)
❓Q3:Shadow DOM 可以嵌套吗?
是的!你可以在组件内再建一个 Shadow DOM。
但一般不建议太深,除非特别需要。
❓Q4:怎么传递属性给组件?
你可以使用属性监听器 attributeChangedCallback 来监听属性变化。
举个例子:
class MyComponent extends HTMLElement {
static get observedAttributes() {
return ['title'];
}
attributeChangedCallback(name, oldVal, newVal) {
if (name === 'title') {
console.log('标题更新为:', newVal);
}
}
}
使用时:
<my-component title="我是标题"></my-component>
学习建议:下一步学什么?
恭喜你完成了第一个 Web Component!
如果你对这个方向感兴趣,下面是一些学习建议:
✅ 建议路线图
🧱 深入 Shadow DOM
- 掌握样式封装原理
- 学习
:host、:host-context等伪类选择器
🔌 掌握通信方式
- 如何触发组件内部的事件并返回数据?
- 了解
Event和自定义事件广播
🪄 使用 Web Component 构建完整应用
- 搭配路由(如 lit-router)
- 状态管理(如 Redux、MobX 的结合)
🧩 学习相关生态库
📘 推荐学习资料
| 类型 | 地址 |
|---|---|
| MDN 文档 | https://developer.mozilla.org/zh-CN/docs/Web/Web_Components |
| WebComponents 官网 | https://www.webcomponents.org/ |
| Lit 文档 | https://lit.dev/docs/ |
| Stencil 文档 | https://stenciljs.com/docs/introduction |

🧠 坚持实践才是王道!
编程最重要的不是记住语法,而是动手写。尝试改写下上面的卡片组件,加入:
- 标题区
- 收起/展开按钮
- 动画效果
每改一次,你就进步了一点!
小结
在这篇文章中,我们学会了:
- Web Components 是什么,有什么用途
- 如何搭建开发环境
- 三大核心概念:Custom Elements、Shadow DOM、HTML Template
- 动手实现了一个卡片组件
- 常见问题的解决方案
- 下一步的学习建议
别忘了反复练习这些知识点,才能真正掌握它。
祝你学得开心!继续加油,成为一个更棒的前端开发者!
📚 如果你喜欢这篇文章,欢迎点赞、收藏或分享给更多刚起步的同学~

评论 0