Web Components:原生组件化开发新趋势(面向初学者)
一、开篇:什么是 Web Components?它有什么用?

你有没有想过,如果我们可以像搭积木一样来开发网页,会有多方便?比如你想做一个按钮组件,只要写一次代码,就可以在任何页面上直接使用这个按钮,不需要重复复制粘贴代码。这种“可复用的网页模块”就是我们今天要讲的 Web Components。
它解决了什么问题?
传统的网页开发中,我们通常需要在多个文件之间手动复制 HTML、CSS 和 JavaScript。这样不仅效率低,而且维护起来也很麻烦。
而 Web Components 提供了一种全新的方式,让我们可以创建自定义的、独立的、可复用的网页组件,就像 Vue 或 React 的组件那样,但它是浏览器原生支持的,无需额外框架。
它有哪些优点?
- ✅ 浏览器原生支持,无需安装框架
- ✅ 组件高度封装,样式和逻辑互不干扰
- ✅ 可跨项目复用,提高开发效率
- ✅ 适合与任何前端技术结合使用
现在我们先来一步一步地了解如何使用它吧!
二、环境准备:搭建你的第一个 Web Components 开发环境


学习 Web Components 并不需要复杂的开发工具。你可以只用一个文本编辑器和一个浏览器就搞定。
步骤 1:安装一个代码编辑器
推荐新手使用 Visual Studio Code (VS Code),它免费、强大、适合写前端代码。
小提示:安装后建议安装以下插件:
- Prettier(美化代码)
- Live Server(本地服务器)
步骤 2:新建项目文件夹结构
在电脑任意位置新建一个项目文件夹,例如叫做 web-components-demo,然后在里面创建以下文件:
web-components-demo/
├── index.html
├── main.js
└── style.css
步骤 3:配置 index.html
打开 index.html,输入以下基本结构:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<title>我的第一个 Web Component</title>
<link rel="stylesheet" href="style.css" />
</head>
<body>
<h1>欢迎来到 Web Components 学习之旅!</h1>
<!-- 稍后我们将在这里添加自定义组件 -->
<my-button>点我试试</my-button>
<script type="module" src="./main.js"></script>
</body>
</html>
这里要注意的是 <script> 标签有一个 type="module",这是 ES6 模块系统的关键标志,Web Components 依赖它。
步骤 4:用 Live Server 启动本地服务器
如果你已经安装了 VS Code 和 Live Server 插件:
- 在 VS Code 中右键点击
index.html - 选择 Open with Live Server
- 浏览器就会自动打开网址,比如:http://127.0.0.1:5500/
这样我们就有了一个最简单的开发环境啦!
三、核心概念:用最通俗的语言解释关键概念

Web Components 主要包括三大核心技术:
自定义元素(Custom Elements)
自定义元素就像是你自己发明的新 HTML 标签。比如本来只有 <button>,但现在你可以创建一个叫 <my-button> 的标签。
示例:创建一个最简单的自定义按钮
在 main.js 文件中输入如下代码:
class MyButton extends HTMLElement {
constructor() {
super();
this.textContent = "我是按钮";
}
}
// 注册组件
customElements.define("my-button", MyButton);
刷新浏览器,你会看到页面中出现了一个按钮,内容是:“我是按钮”。
📌 小知识点:
extends HTMLElement表示这是一个 HTML 元素。constructor()是构造函数,在组件被创建时自动执行。customElements.define()是注册组件的方法,括号中的第一个参数是自定义标签名。
Shadow DOM(影子 DOM)
有时候我们会担心自己的组件样式会不会和全局 CSS 冲突,这时候就需要 Shadow DOM 来隔离样式。
示例:给按钮加阴影 DOM
修改 main.js 如下:
class MyButton extends HTMLElement {
constructor() {
super();
// 创建 Shadow DOM
const shadow = this.attachShadow({ mode: 'open' });
// 创建按钮元素
const button = document.createElement('button');
button.textContent = '点我';
// 创建样式
const style = document.createElement('style');
style.textContent = `
button {
background-color: lightblue;
padding: 10px 20px;
border-radius: 5px;
cursor: pointer;
}
`;
// 把样式和按钮加入 shadow dom
shadow.appendChild(style);
shadow.appendChild(button);
}
}
customElements.define("my-button", MyButton);
这样这个按钮的样式就被隔离了,不会受到外面 style.css 文件的影响。
📌 新手问答:
Q:shadow dom 里的样式会影响其他元素吗?
A:不会,shadow dom 是独立的,样式只作用于该组件。
HTML 模板(Template)
每次都要动态创建 HTML 和样式太麻烦了。HTML 提供了 <template> 标签,可以让我们预先定义好模板,使用时直接插入即可。
示例:使用 template 模板创建按钮
首先,在 index.html 中增加一段模板:
<template id="my-button-template">
<style>
button {
background-color: lightgreen;
padding: 10px 20px;
border-radius: 5px;
cursor: pointer;
}
</style>
<button><slot></slot></button>
</template>
然后修改 main.js 使用这个模板:
class MyButton extends HTMLElement {
constructor() {
super();
const template = document.getElementById("my-button-template");
const shadow = this.attachShadow({ mode: "open" });
// 复制模板内容到 shadow dom
const instance = template.content.cloneNode(true);
shadow.appendChild(instance);
}
}
customElements.define("my-button", MyButton);
这时你再刷新页面,就能看到绿色按钮出现了,并且你在 <my-button> 标签之间写的文字,比如:
<my-button>登录</my-button>
会被显示出来,因为用了 <slot> 占位符。
📌 新手问答:
Q:slot 是干嘛的?
A:slot 就是一个占位符,允许你在调用组件时填入自定义内容。
四、实战项目:创建一个可复用的“欢迎卡片”组件
接下来我们要动手做一个小项目:创建一个通用的欢迎卡片组件。它可以显示用户名和欢迎信息,并有关闭功能。
第一步:添加模板到 HTML
在 index.html 中添加以下 <template>:
<template id="welcome-card">
<style>
.card {
width: 300px;
padding: 20px;
border: 1px solid #ccc;
border-radius: 8px;
background-color: #f9f9f9;
font-family: Arial, sans-serif;
}
.title {
font-size: 1.2em;
margin-bottom: 10px;
}
.close-btn {
float: right;
color: red;
cursor: pointer;
}
</style>
<div class="card">
<span class="close-btn">✖</span>
<div class="title"><slot name="username">默认用户</slot>,你好!</div>
<p><slot name="message">欢迎访问本网站</slot></p>
</div>
</template>
第二步:编写组件 JS 逻辑
在 main.js 中添加以下代码:
class WelcomeCard extends HTMLElement {
constructor() {
super();
const template = document.getElementById("welcome-card");
const shadow = this.attachShadow({ mode: "open" });
const clone = template.content.cloneNode(true);
// 获取关闭按钮并添加点击事件
const closeBtn = clone.querySelector(".close-btn");
closeBtn.addEventListener("click", () => {
this.remove(); // 删除整个卡片
});
shadow.appendChild(clone);
}
}
customElements.define("welcome-card", WelcomeCard);
第三步:在 HTML 页面中使用组件
现在你可以随便在页面中插入多个欢迎卡片了:
<welcome-card>
<span slot="username">小明</span>
<span slot="message">欢迎回来,继续学习 Web Components!</span>
</welcome-card>
<welcome-card>
<span slot="username">小白</span>
<span slot="message">第一次来这里,很高兴认识你!</span>
</welcome-card>
效果就是两个带用户名和消息的小卡片,还有一个点击 × 就消失的功能。
五、常见问题解答(FAQ)

Q1:为什么我的自定义标签没有显示?
可能原因:
- 没有正确注册组件:确保
customElements.define()被执行。 - 标签名不符合规范:必须包含一个短横线
-,例如<my-button>是对的,<button>是无效的。 - 页面加载顺序不对:JS 必须在 DOM 加载之后执行。
Q2:样式没生效,或者影响到了其他地方?
建议做法:
- 使用 Shadow DOM 来隔离样式。
- 避免在全局样式中设置通用样式,否则容易影响到组件内部样式。
Q3:slot 里传不了内容怎么办?
检查一下:
- slot 是否有
name属性? - 在使用组件时是否正确设置了
slot="xxx"? - 组件是否成功渲染?可以在控制台输出
this.shadowRoot查看是否有内容。
六、学习建议:下一步怎么学?
恭喜你完成了这个入门教程!你现在已经有能力写简单的 Web Components 了。接下来你可以沿着以下几个方向继续深入学习:
1. 更复杂的状态管理
可以尝试在组件中添加状态(state)和生命周期方法,比如响应点击、数据更新等。
2. 学习 observedAttributes 实现属性监听
让组件能够通过 HTML 属性传递数据,比如这样写:
<my-input value="你好" placeholder="请输入…"></my-input>
3. 接入构建工具(如 Vite)
虽然基础版可以直接运行,但当你做大型项目时,还是需要用工具来打包优化。
4. 和现代框架融合使用
Web Components 可以和 Vue、React、Angular 等现代前端框架无缝协作,是一个不错的技能组合。
结语
Web Components 是一种轻量、强大、未来感十足的技术,它让你可以用最原生的方式写出可复用、易维护的组件。希望这篇教程能为你打开一扇新的大门。
记住一句话:
“编程不是难事,只要肯动手。”
加油,一起成为更好的开发者吧!🌟

评论 0