Web Components:不用框架也能写组件的原生魔法

Cloud大数据
2025-12-29 19:17
阅读 772

大家好,我是一个从中文系转行做前端的“野生程序员”。当初学前端时,被 React、Vue 这些框架绕得晕头转向——为什么写个按钮都要先装一堆依赖?后来我偶然接触到 Web Components,才发现:原来浏览器早就支持“组件化”了!不用任何框架,靠原生能力就能封装可复用的 UI 模块。

今天这篇教程,就是想带零基础的朋友亲手试试这个被低估的原生技术。哪怕你连 <div> 都没写过,也能跟着做出自己的第一个 Web Component!


为什么现在要学 Web Components?

很多初学者一上来就学 React,但其实 Web Components 是浏览器原生支持的组件化方案。这意味着:

  • 不需要打包工具(Webpack/Vite)
  • 不依赖任何第三方库
  • 和 React、Vue 完全兼容(甚至能嵌套使用!)

💡 小知识:React 官方文档里专门有一节讲 如何在 React 中使用 Web Components,说明它不是“替代品”,而是“补充”。


环境准备:5 分钟搞定开发环境

Web Components 最大的优点就是开箱即用!你只需要:

  1. 一个现代浏览器(Chrome/Firefox/Edge 最新版)
  2. 任意文本编辑器(VS Code、记事本都行)
  3. 一个 .html 文件

验证步骤

  1. 新建 index.html
  2. 用浏览器打开
  3. 打开开发者工具(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. 保存文件并用浏览器打开
  2. 点击按钮,会变成红色并显示 👍 1
  3. 再点无效(因为我们只允许点一次)

关键点解析

  • attachShadow({ mode: 'open' }):创建可被 JS 访问的 Shadow DOM
  • customElements.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 相关问题,试试你能答对几道?

  1. Q:Web Components 能和 React 一起用吗?
    A:可以!React 可以渲染自定义元素(注意属性要用 camelCasekebab-case)。

  2. Q:Shadow DOM 的 mode: 'open''closed' 有什么区别?
    A:open 允许外部通过 element.shadowRoot 访问内部;closed 则完全封闭(但实际很少用)。

  3. 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 虽然简单,但要写出生产级组件还需要深入:

  1. 学习生命周期方法connectedCallback(插入 DOM 时)、disconnectedCallback(移除时)
  2. 掌握属性监听:用 observedAttributes + attributeChangedCallback 实现响应式更新
  3. 尝试模板化:用 <template> 标签分离 HTML 结构
  4. 探索工具库:如 Lit(Google 出品,简化 Web Components 开发)

📌 我的建议:先用原生写几个小组件(比如天气卡片、计数器),再对比 React 实现——你会对“组件化”有更深理解。


结语:技术没有银弹,只有合适场景

我当初死磕 React 半年,回头发现 Web Components 才是“大道至简”。它可能不适合构建整个应用,但在跨技术栈复用微前端轻量插件等场景下无可替代。

这篇教程只讲了最基础的部分,但只要你动手敲一遍代码,就已经超过了 80% 只看不练的人。记住:所有复杂的框架,底层都是这些原生 API 的封装

下次面试被问到“了解 Web Components 吗?”,你可以自信地说:“我不仅用过,还自己造过轮子。”

🛠️ 课后小任务:试着给点赞按钮加一个 max-count 属性,限制最多点 5 次。遇到问题?欢迎留言讨论!

评论 0

最热最新
暂无评论
匿名用户Lv.1
0
影响力
0
文章
0
粉丝