Web Components:不用框架也能写组件的原生魔法
大家好,我是一个从中文系转行做前端的“野生程序员”。当初学前端时,被 React、Vue 这些框架绕得晕头转向——为什么写个按钮都要先装一堆依赖?后来我偶然接触到 Web Components,才发现:原来浏览器早就支持“组件化”了!不用任何框架,靠原生能力就能封装可复用的 UI 模块。
今天这篇教程,就是想带零基础的朋友亲手试试这个被低估的原生技术。哪怕你连 <div> 都没写过,也能跟着做出自己的第一个 Web Component!
为什么现在要学 Web Components?
很多初学者一上来就学 React,但其实 Web Components 是浏览器原生支持的组件化方案。这意味着:
- 不需要打包工具(Webpack/Vite)
- 不依赖任何第三方库
- 和 React、Vue 完全兼容(甚至能嵌套使用!)
💡 小知识:React 官方文档里专门有一节讲 如何在 React 中使用 Web Components,说明它不是“替代品”,而是“补充”。
环境准备:5 分钟搞定开发环境
Web Components 最大的优点就是开箱即用!你只需要:
- 一个现代浏览器(Chrome/Firefox/Edge 最新版)
- 任意文本编辑器(VS Code、记事本都行)
- 一个
.html文件
✅ 验证步骤:
- 新建
index.html- 用浏览器打开
- 打开开发者工具(F12)——如果没报错,环境就 ready 了!
不需要 Node.js,不需要 npm install,这就是原生的力量。
三大核心概念,一张表说清楚
Web Components 其实由三个浏览器 API 组成:
| 技术 | 作用 | 类比理解 |
|---|---|---|
| Custom Elements | 定义新 HTML 标签(如 <my-button>) |
就像发明一个新单词 |
| Shadow DOM | 隔离组件内部样式和结构 | 组件自带“玻璃罩”,外面 CSS 影响不到里面 |
| HTML Templates | 声明可复用的 HTML 片段 | 像 Word 里的“模板”,填数据就能用 |
🌟 我当初学的时候以为 Shadow DOM 很复杂,其实它就是一个“私有空间”——你在里面写的样式不会污染全局,外面的样式也进不来。
实战:手写一个「点赞按钮」组件
我们来做一个最简单的 Web Component:点击按钮,数字 +1,并改变颜色。
第一步:定义组件类
<!-- index.html -->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>我的第一个 Web Component</title>
</head>
<body>
<!-- 使用自定义标签 -->
<like-button></like-button>
<script>
// 1. 创建组件类
class LikeButton extends HTMLElement {
constructor() {
super(); // 必须调用父类构造函数
// 2. 创建 Shadow DOM
const shadow = this.attachShadow({ mode: 'open' });
// 3. 定义内部 HTML 和样式
shadow.innerHTML = `
<style>
.btn {
padding: 8px 16px;
border: none;
border-radius: 4px;
background: #eee;
cursor: pointer;
font-size: 16px;
}
.liked {
background: #ff6b6b;
color: white;
}
</style>
<button class="btn">👍 0</button>
`;
// 4. 绑定点击事件
const button = shadow.querySelector('button');
let count = 0;
let liked = false;
button.addEventListener('click', () => {
if (!liked) {
count++;
liked = true;
button.textContent = `👍 ${count}`;
button.classList.add('liked');
}
});
}
}
// 5. 注册自定义元素
customElements.define('like-button', LikeButton);
</script>
</body>
</html>
第二步:运行效果
- 保存文件并用浏览器打开
- 点击按钮,会变成红色并显示 👍 1
- 再点无效(因为我们只允许点一次)
✅ 关键点解析:
attachShadow({ mode: 'open' }):创建可被 JS 访问的 Shadow DOMcustomElements.define():把类注册为 HTML 标签- 标签名必须带短横线(如
like-button),这是规范!
和 React 对比:谁更适合你?
很多新手会问:“既然有 React,还要学 Web Components 吗?”
| 场景 | 推荐方案 |
|---|---|
| 大型应用、复杂状态管理 | React/Vue |
| 微前端、跨框架复用组件 | Web Components |
| 快速原型、轻量级插件 | Web Components |
| 团队已熟练使用 React | React |
💬 真实案例:我上家公司用 React 写主站,但客服聊天窗口是用 Web Components 做的——因为它要嵌入到客户网站(可能是 PHP/WordPress),不能依赖 React 运行时。
面试题挑战:3 道高频题自测
面试官常问 Web Components 相关问题,试试你能答对几道?
Q:Web Components 能和 React 一起用吗?
A:可以!React 可以渲染自定义元素(注意属性要用camelCase转kebab-case)。Q:Shadow DOM 的
mode: 'open'和'closed'有什么区别?
A:open允许外部通过element.shadowRoot访问内部;closed则完全封闭(但实际很少用)。Q:如何给 Web Component 传参?
A:通过 HTML 属性(如<my-comp name="Alice">),在组件内用this.getAttribute('name')读取。
🔍 避坑指南:属性更新不会自动触发重渲染!需要用
attributeChangedCallback监听变化(进阶内容,初学可先忽略)。
新手常见问题解答
❓ 问题 1:为什么我的组件不显示?
- 检查标签名是否带短横线(
<mybutton>❌,<my-button>✅) - 检查是否调用了
customElements.define() - 检查是否在 DOM 加载完成后注册(或把
<script>放在</body>前)
❓ 问题 2:样式怎么不生效?
- 确保样式写在
shadow.innerHTML的<style>标签内 - 外部 CSS 无法穿透到 Shadow DOM(这是特性,不是 bug!)
❓ 问题 3:能用 npm 包吗?
可以!但要注意:
- 如果包依赖 React/Vue,就不能直接用
- 纯 JS 工具库(如 Lodash)可以正常使用
下一步学习建议
Web Components 虽然简单,但要写出生产级组件还需要深入:
- 学习生命周期方法:
connectedCallback(插入 DOM 时)、disconnectedCallback(移除时) - 掌握属性监听:用
observedAttributes+attributeChangedCallback实现响应式更新 - 尝试模板化:用
<template>标签分离 HTML 结构 - 探索工具库:如 Lit(Google 出品,简化 Web Components 开发)
📌 我的建议:先用原生写几个小组件(比如天气卡片、计数器),再对比 React 实现——你会对“组件化”有更深理解。
结语:技术没有银弹,只有合适场景
我当初死磕 React 半年,回头发现 Web Components 才是“大道至简”。它可能不适合构建整个应用,但在跨技术栈复用、微前端、轻量插件等场景下无可替代。
这篇教程只讲了最基础的部分,但只要你动手敲一遍代码,就已经超过了 80% 只看不练的人。记住:所有复杂的框架,底层都是这些原生 API 的封装。
下次面试被问到“了解 Web Components 吗?”,你可以自信地说:“我不仅用过,还自己造过轮子。”
🛠️ 课后小任务:试着给点赞按钮加一个
max-count属性,限制最多点 5 次。遇到问题?欢迎留言讨论!

评论 0