Web Components:原生组件化开发,你真的不需要框架吗?
大家好,我是阿杰,一名在大厂干了三年前端的老兵,业余时间也在B站做技术分享。最近不少刚入门的同学问我:“现在都2024年了,React/Vue 那么火,为什么还要学 Web Components?”其实这个问题我也在面试中被问过——没错,Web Components 已经悄悄成为大厂前端面试的新考点!
今天这篇教程,就是专门为零基础朋友准备的。我会用最直白的语言、最少的术语,带你从零开始搞懂 Web Components。更重要的是,我会告诉你:它和 React 有什么区别?为什么连 Python 开发者也开始关注它?以及如何用 Claude Code 辅助你快速上手?
一、Web Components 到底是什么?
简单说:Web Components 是浏览器原生支持的“自定义 HTML 标签”能力。
你有没有想过,为什么 <button>、<input> 这些标签可以直接用?因为浏览器内置了它们。而 Web Components 让你也能“造”出自己的标签,比如 <my-header>、<user-card>,而且不用依赖 React、Vue 等任何框架!
我当初学的时候,以为这东西很冷门。结果后来发现,像 YouTube、GitHub、Salesforce 这些大厂早已在生产环境大量使用。更关键的是——它性能极高,因为是浏览器原生实现,没有虚拟 DOM 的开销。
二、环境准备:5分钟搞定开发环境
好消息是:你几乎不需要额外安装任何东西!只要你的电脑有:
- 最新版 Chrome / Edge / Firefox(都已全面支持)
- 一个文本编辑器(VS Code、记事本都行)
💡 避坑指南:别装什么“Web Components 框架”!我们要学的是原生写法,这才是面试官想考的。
创建一个项目文件夹,新建 index.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>我的第一个 Web Component</title>
</head>
<body>
<!-- 我们的自定义组件会放这里 -->
<my-greeting name="小明"></my-greeting>
<script src="main.js"></script>
</body>
</html>
再新建 main.js,我们就准备好了!
三、三大核心概念,一张表说清楚
Web Components 由三个原生 API 组成。别怕,其实很简单:
| 技术 | 作用 | 类比理解 |
|---|---|---|
| Custom Elements | 定义新 HTML 标签名 | 就像给 HTML “注册”一个新零件 |
| Shadow DOM | 实现样式和 DOM 隔离 | 组件内部是个“独立小世界”,外面样式进不来 |
| HTML Templates | 声明可复用的 HTML 结构 | 先写好“模具”,需要时再复制出来 |
下面逐个拆解,带代码实操。
1. Custom Elements:定义你的第一个组件
在 main.js 中写下这段代码:
class MyGreeting extends HTMLElement {
constructor() {
super(); // 必须调用父类构造器
this.innerHTML = `<h1>Hello, ${this.getAttribute('name')}!</h1>`;
}
}
// 注册组件:告诉浏览器 "<my-greeting>" 对应哪个类
customElements.define('my-greeting', MyGreeting);
刷新页面,你会看到:Hello, 小明!
✅ 新手注意:
- 组件名必须包含
-(短横线),比如user-card,不能叫userCardgetAttribute用来读取 HTML 属性(如name="小明")
2. Shadow DOM:让样式不打架
假设你在全局写了 h1 { color: red; },会影响组件内的 h1 吗?不会! 因为我们可以用 Shadow DOM 隔离。
修改 MyGreeting 类:
class MyGreeting extends HTMLElement {
constructor() {
super();
// 创建 Shadow DOM
const shadow = this.attachShadow({ mode: 'open' });
// 内部 HTML 和 CSS
shadow.innerHTML = `
<style>
h1 { color: blue; font-family: Arial; }
</style>
<h1>Hello, ${this.getAttribute('name')}!</h1>
`;
}
}
现在,无论页面其他地方怎么改 h1 样式,这个组件始终是蓝色!
💡 性能优化提示:Shadow DOM 能避免样式污染,减少重绘重排,提升渲染性能。
3. Template:复用结构模板
如果组件结构复杂,每次都拼字符串很麻烦。这时用 <template>:
在 index.html 的 <head> 里加:
<template id="greeting-template">
<style>
h1 { color: green; }
</style>
<h1>Hello, <span class="name"></span>!</h1>
</template>
然后在 JS 中克隆使用:
class MyGreeting extends HTMLElement {
constructor() {
super();
const shadow = this.attachShadow({ mode: 'open' });
// 获取模板并克隆
const template = document.getElementById('greeting-template');
const instance = template.content.cloneNode(true);
// 设置名字
instance.querySelector('.name').textContent = this.getAttribute('name');
shadow.appendChild(instance);
}
}
customElements.define('my-greeting', MyGreeting);
这样,HTML 结构和逻辑分离,代码更清晰!
四、实战项目:做一个用户信息卡片
现在,我们综合运用所学,做一个 <user-card> 组件。
步骤 1:HTML 结构
<user-card
avatar="https://example.com/avatar.jpg"
name="张三"
bio="前端工程师 | 爱好编程和咖啡">
</user-card>
步骤 2:定义组件
class UserCard extends HTMLElement {
constructor() {
super();
const shadow = this.attachShadow({ mode: 'open' });
// 使用模板方式(也可直接拼字符串)
shadow.innerHTML = `
<style>
.card {
border: 1px solid #ddd;
border-radius: 8px;
padding: 16px;
max-width: 300px;
font-family: sans-serif;
}
img {
width: 60px;
height: 60px;
border-radius: 50%;
object-fit: cover;
}
.info { margin-top: 12px; }
h2 { margin: 8px 0 4px; }
p { color: #666; margin: 0; }
</style>
<div class="card">
<img src="${this.getAttribute('avatar')}" alt="头像">
<div class="info">
<h2>${this.getAttribute('name')}</h2>
<p>${this.getAttribute('bio')}</p>
</div>
</div>
`;
}
}
customElements.define('user-card', UserCard);
步骤 3:测试效果
在页面多放几个:
<user-card avatar="a.jpg" name="李四" bio="设计师"></user-card>
<user-card avatar="b.jpg" name="王五" bio="Python后端"></user-card>
每个卡片完全独立,样式互不影响!
🎯 面试题挑战:
Q:Web Components 和 React 组件有什么本质区别?
A:React 组件是 JS 函数 + 虚拟 DOM,依赖运行时;Web Components 是浏览器原生能力,无需框架,性能更高,但生态较弱。
五、新手常见问题解答
❓ 1. 能和 React/Vue 一起用吗?
可以! 很多公司用 Web Components 封装底层 UI(如按钮、弹窗),再在 React 中调用。例如:
// React 组件中直接使用
function App() {
return <user-card name="React用户" />;
}
❓ 2. 数据怎么更新?有状态管理吗?
原生 Web Components 没有内置状态系统。但你可以:
- 监听属性变化(用
attributeChangedCallback) - 或结合轻量库(如 Lit)简化开发
❓ 3. Python 开发者为什么要关心?
现在很多 Python Web 框架(如 Django、Flask)输出的是服务端 HTML。用 Web Components 可以在后端直接嵌入交互组件,无需引入前端构建工具链,特别适合快速原型开发!
❓ 4. 如何用 Claude Code 辅助学习?
我在 B站 视频里常用 Claude 生成 Web Components 示例代码。比如输入:
“用原生 Web Components 写一个带计数器的按钮组件”
它能快速给你完整代码,省去查文档时间。但记得自己动手改几遍,才能真正掌握!
六、下一步学习建议
如果你已经跑通了上面的例子,恭喜你入门了!接下来可以:
- 深入学习生命周期:了解
connectedCallback、disconnectedCallback等钩子 - 尝试 Lit 库:Google 出品的轻量 Web Components 库,语法更简洁
- 对比 React:试着把同一个组件分别用 React 和 Web Components 实现,感受差异
- 参与开源:看看 GitHub 上哪些项目用了 Web Components(如 Shoelace、FAST)
⚠️ 最后提醒:Web Components 不是 React 的替代品,而是另一种思路。大厂往往两者并用——核心交互用 React,基础 UI 用 Web Components 提升性能。
结语
我当初学前端时,只盯着 React,觉得原生 DOM 操作“过时了”。直到一次性能优化任务,才意识到:有时候,最简单的原生方案,反而是最高效的。
Web Components 就是这样一个“返璞归真”的技术。它可能不会让你立刻找到工作,但一定能让你在面试中脱颖而出,尤其是在考察“底层原理”和“性能优化”时。
如果你觉得这篇教程有帮助,欢迎去 B站 搜“阿杰前端课”,我会持续更新更多实战内容。下期见!

评论 0