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

想象一下,你去超市买东西,想做蛋糕。如果你得从面粉、鸡蛋开始一步步做起,那很麻烦。但如果超市里已经有现成的“蛋糕半成品包”,你只需要把它们组合起来就能完成整个蛋糕,是不是更轻松了?
在网页开发中也是一样的道理。Web Components 就像是这样一种“半成品包”——它允许我们创建可重用的网页组件,这些组件就像一个个小零件,可以随时拿出来组装到任何网页中。
而且最重要的是:它不需要依赖任何框架(比如 Vue 或 React),而是直接使用浏览器自带的能力来实现的!
一句话总结:Web Components 是一项基于浏览器原生特性的技术,用来创建和复用自定义的 HTML 标签。
环境准备:搭建开发环境

在开始学习之前,你需要准备好一个最基础的开发环境。
✅ 所需工具列表:
- 一台电脑(Windows、Mac 或 Linux 都行)
- 浏览器(推荐 Chrome 或 Firefox)
- 文本编辑器(推荐 VS Code)
- 基础的 HTML/CSS/JavaScript 知识(不用担心太深,有基础就行)
🧰 操作步骤:
安装 VS Code
- 前往 https://code.visualstudio.com 下载并安装
- 安装完成后打开它
创建项目文件夹
- 在你的电脑上新建一个文件夹,比如
web-components-demo
- 在你的电脑上新建一个文件夹,比如
在 VS Code 中打开该文件夹
- 启动 VS Code -> 文件菜单 -> 打开文件夹 -> 选择你刚刚创建的文件夹
创建一个测试 HTML 文件
- 右键点击空白处 -> 新建文件 -> 输入
index.html
- 右键点击空白处 -> 新建文件 -> 输入
写入如下内容作为测试代码:
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>Web Components 初体验</title>
</head>
<body>
<h1>Hello, Web Components!</h1>
<script src="demo.js"></script>
</body>
</html>

- 再创建一个 JS 文件
demo.js- 在同一个目录下新建文件,输入以下代码即可:
console.log("Hello from JavaScript");
- 用浏览器打开这个 HTML 文件
- 直接右键
index.html-> 使用浏览器打开 - 打开控制台(F12 或右键页面选择“检查”)可以看到输出的信息
- 直接右键
✅ 成功!你现在有了一个简单的开发环境,接下来就可以开始学习 Web Components 的核心知识啦!
核心概念:什么是 Web Components?

Web Components 其实包含三大核心技术:
| 技术名称 | 作用 |
|---|---|
| 自定义元素(Custom Elements) | 创建自己的 HTML 标签,例如 <my-button> |
| 阴影 DOM(Shadow DOM) | 让组件内部的结构与样式与外部隔离,互不干扰 |
| HTML 模板(HTML Templates) | 为组件定义可复用的结构模板 |
我们来分别理解这三个概念,并配上示例。
🌱 1. 自定义元素(Custom Elements)
这是 Web Components 的核心之一。我们可以像定义 div 或 span 一样定义自己的标签。
示例:创建一个 <hello-world> 组件
// demo.js
class HelloWorld extends HTMLElement {
constructor() {
super(); // 必须写这句
this.innerHTML = "你好,世界!";
}
}
customElements.define('hello-world', HelloWorld);
然后我们在 HTML 中使用它:
<hello-world></hello-world>
刷新页面,你应该看到 “你好,世界!” 出现在页面上。
🔍 新手提问:为什么要继承 HTMLElement?
这是因为所有 HTML 元素本质上都是这个类的子类。我们要创建自定义标签,就必须让它具备基本的 HTML 元素行为。
🎭 2. 阴影 DOM(Shadow DOM)
Shadow DOM 的最大特点就是封装能力 —— 它让组件内的样式和结构对外隐藏,不会被全局样式干扰。
示例:用 Shadow DOM 封装一个按钮组件
// demo.js
class MyButton extends HTMLElement {
constructor() {
super();
const shadow = this.attachShadow({ mode: 'open' });
// 创建按钮元素
const button = document.createElement('button');
button.textContent = '点我';
button.style.backgroundColor = 'lightblue';
button.style.borderRadius = '5px';
// 添加事件监听器
button.addEventListener('click', () => {
alert('你点了按钮!');
});
// 把按钮插入到 shadow DOM 中
shadow.appendChild(button);
}
}
customElements.define('my-button', MyButton);
使用方式:
<my-button></my-button>
效果:你会看到一个蓝色按钮,点击会有弹窗提示,但它的样式不会影响你页面上的其他按钮。
🔍 新手提问:什么是模式(mode)?open 和 closed 有什么区别?
open:shadow root 可以通过 JS 获取(方便调试和访问)closed:不能通过 JS 获取,更加封闭(适合封装性要求高的场景)
📄 3. HTML 模板(Templates)
如果每次都要手动创建元素,写一大堆 DOM 操作,就显得比较笨拙了。这时候我们可以使用 <template> 标签来提前写好结构。
示例:使用模板创建一个卡片组件
<!-- index.html -->
<template id="card-template">
<style>
.card {
border: 1px solid #ccc;
padding: 10px;
margin: 10px;
width: 200px;
}
</style>
<div class="card">
<h3>默认标题</h3>
<p>这里是默认内容</p>
</div>
</template>
然后用 JS 加载模板:
// demo.js
class MyCard extends HTMLElement {
constructor() {
super();
const template = document.getElementById('card-template');
const content = template.content.cloneNode(true); // true 表示复制全部子节点
const shadow = this.attachShadow({ mode: 'open' });
shadow.appendChild(content);
}
}
customElements.define('my-card', MyCard);
使用方式:
<my-card></my-card>
效果:你会看到一个带有样式的卡片,且样式只在这个组件内部生效。
实战项目:做一个带标题和内容的卡片组件

现在我们来实战制作一个完整的组件,功能包括:
- 支持设置标题和内容
- 每次点击展开或收起内容
🔧 第一步:编写 HTML 模板
<!-- index.html -->
<template id="expander-card">
<style>
.card {
border: 1px solid #ddd;
padding: 10px;
margin: 10px;
max-width: 300px;
cursor: pointer;
}
.content {
display: none;
}
</style>

<div class="card">
<h3 id="title">标题</h3>
<div id="content" class="content">
<p>这里是隐藏的内容区域。</p>
</div>
</div>
</template>
💻 第二步:用 JS 创建组件
// demo.js
class ExpanderCard extends HTMLElement {
constructor() {
super();
const template = document.getElementById('expander-card');
const content = template.content.cloneNode(true);
const shadow = this.attachShadow({ mode: 'open' });
shadow.appendChild(content);
// 获取 shadow 内部的元素
const title = shadow.querySelector('#title');
const contentDiv = shadow.querySelector('#content');
// 设置标题和内容(来自自定义属性)
title.textContent = this.getAttribute('title') || '默认标题';
contentDiv.querySelector('p').textContent = this.getAttribute('content') || '默认内容';
// 点击切换显示/隐藏
const card = shadow.querySelector('.card');
let visible = false;
card.addEventListener('click', () => {
visible = !visible;
contentDiv.style.display = visible ? 'block' : 'none';
});
}
}
customElements.define('expander-card', ExpanderCard);
🎯 第三步:使用组件
<expander-card title="我是标题" content="点击展开详细信息"></expander-card>
刷新页面,点击卡片试试看吧!
常见问题:新手易犯错误及解答
❓1. 为什么我的自定义标签不显示?
可能原因:
- 没有正确调用
customElements.define - 类名没写对或拼写错了
- 标签名必须包含短横线(如
my-card而不是mycard)
✅ 解决办法:检查拼写、语法是否正确。
❓2. 组件样式为什么失效了?
可能原因:
- 样式未放进
shadow DOM中 - 外部样式污染了组件样式
✅ 解决办法:将样式写在 <template> 内或者直接添加到 shadow DOM。
❓3. 如何给组件传参数?
可以通过 HTML 属性传递数据,比如:
<my-component data-name="Tom"></my-component>
然后在 JS 中用 this.getAttribute('data-name') 获取。
学习建议:下一步可以学什么?
掌握 Web Components 后,你可以考虑以下几个方向继续深入学习:
🧭 方向一:结合框架使用(Vue / React / Angular)
虽然 Web Components 本身是原生的,但它可以在主流前端框架中使用,甚至可以用它构建跨框架的组件库。
🔗 推荐资源:
💡 方向二:尝试开发自己的组件库
试着做出一些通用组件:按钮、输入框、导航条等,慢慢积累一个自己的“组件包”。
🚀 方向三:了解现代 Web 开发最佳实践
学习如何打包组件、部署上线,以及如何用工具管理多个组件(比如使用 npm 发布组件)。
恭喜你完成了第一篇 Web Components 入门教程!希望你能动手跟着练习一遍,理解每个知识点背后的原理。接下来的学习会越来越有趣,加油!

评论 0