Web Components:原生组件化开发新趋势(零基础入门实战)

胡浩宇~
2025-12-15 07:23
阅读 200

大家好,我是一名干了5年后端开发的老程序员。虽然主业是后端,但我一直对前端技术保持关注。最近几年,我发现越来越多团队开始尝试 Web Components —— 一种用原生 JavaScript 实现组件化的技术。不少朋友问我:“这和 React 有什么区别?值得学吗?”

我当初学的时候也是一头雾水。今天,我就用最直白的语言,带完全零基础的你,从零搭建一个 Web Components 小项目,彻底搞懂它到底是什么、怎么用、值不值得学。


一、Web Components 是什么?能用来做什么?

简单说:Web Components 是浏览器原生支持的“搭积木”方式写网页。

  • 你可以把一个功能(比如一个按钮、一个天气卡片)封装成一个独立的“组件”
  • 这个组件自带 HTML + CSS + JS,别人用的时候只需写一行 <my-button></my-button>
  • 不依赖任何框架(如 React、Vue),纯靠浏览器内置能力

最大优势:轻量、标准、跨框架兼容
注意:它不是要取代 React,而是提供另一种选择


二、环境准备:30秒搞定开发环境

好消息是:你不需要安装任何工具! 只需要:

  1. 一台电脑
  2. 一个现代浏览器(Chrome / Edge / Firefox / Safari)
  3. 一个文本编辑器(推荐 VS Code,但记事本也行)

💡 我当初学的时候还傻乎乎地装了一堆构建工具,结果发现根本用不上!

创建项目目录:

mkdir web-components-demo
cd web-components-demo
touch index.html my-counter.js

就这两文件,够了!


三、核心概念:三大支柱(用大白话解释)

Web Components 由三个浏览器原生 API 组成:

技术 作用 类比
Custom Elements 自定义 HTML 标签 就像发明新标签 <my-alert>
Shadow DOM 隔离 CSS 和 DOM 组件的“私人小房间”,外面样式进不来
HTML Templates 定义组件结构模板 像模具,可以反复复制

下面通过一个“计数器”组件,一步步带你理解。


四、实战项目:手写一个 <my-counter> 组件

第一步:在 index.html 中引入组件

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>Web Components 入门</title>
</head>
<body>
  <!-- 使用自定义组件 -->
  <my-counter initial="5"></my-counter>

  <!-- 引入组件定义 -->
  <script src="my-counter.js"></script>
</body>
</html>

第二步:编写 my-counter.js

// 1. 定义组件类(继承 HTMLElement)
class MyCounter extends HTMLElement {
  // 2. 构造函数
  constructor() {
    super(); // 必须调用 super()

    // 3. 创建 Shadow DOM(隔离样式和结构)
    const shadow = this.attachShadow({ mode: 'open' });

    // 4. 获取初始值(从 HTML 属性读取)
    const initialValue = parseInt(this.getAttribute('initial') || '0');

    // 5. 定义模板(HTML + CSS)
    const template = `
      <style>
        .counter {
          padding: 10px;
          border: 2px solid #333;
          display: inline-block;
          font-family: Arial;
        }
        button {
          margin: 0 5px;
          padding: 5px 10px;
        }
      </style>
      <div class="counter">
        <span id="value">${initialValue}</span>
        <button id="decrease">-</button>
        <button id="increase">+</button>
      </div>
    `;

    // 6. 将模板插入 Shadow DOM
    shadow.innerHTML = template;

    // 7. 获取元素引用
    this.valueEl = shadow.getElementById('value');
    this.decreaseBtn = shadow.getElementById('decrease');
    this.increaseBtn = shadow.getElementById('increase');

    // 8. 初始化计数值
    this.count = initialValue;

    // 9. 绑定事件
    this.decreaseBtn.addEventListener('click', () => {
      this.count--;
      this.valueEl.textContent = this.count;
    });

    this.increaseBtn.addEventListener('click', () => {
      this.count++;
      this.valueEl.textContent = this.count;
    });
  }
}

// 10. 注册自定义元素
customElements.define('my-counter', MyCounter);

第三步:运行看看!

双击打开 index.html,你会看到:

[5] [-] [+]

点击 -+,数字会变化!而且你会发现:

  • 外部页面的 CSS 不会影响这个组件(因为用了 Shadow DOM)
  • 如果你在页面其他地方再写一个 <my-counter initial="10"></my-counter>,它会独立工作

🎯 关键点:整个组件逻辑、样式、结构全部封装在一个 .js 文件里,复用极其简单!


五、新手常见问题 & 解答

Q1:Web Components 和 React 组件有什么区别?

对比项 Web Components React
依赖 无(浏览器原生) 需要 React 库
学习成本 低(只需 JS 基础) 较高(JSX、状态管理等)
生态 较小 极其丰富
性能 轻量 需要 Virtual DOM 开销
适用场景 简单 UI 组件、跨框架共享 复杂应用、大型项目

💡 建议:如果你只是想封装几个通用 UI 组件(比如按钮、卡片),Web Components 更轻便;如果是做完整应用,React 仍是首选。

Q2:Shadow DOM 的 mode: 'open''closed' 有啥区别?

  • 'open':外部 JS 可以通过 element.shadowRoot 访问内部 DOM(调试方便)
  • 'closed':完全封闭,外部无法访问(安全性更高,但一般用不到)

初学者用 'open' 即可。

Q3:能不能传复杂数据(比如对象)给组件?

可以,但要注意:

  • HTML 属性只能传字符串
  • 如果要传对象,建议用 JS 动态设置属性:
const counter = document.querySelector('my-counter');
counter.data = { user: 'Alice', score: 100 }; // 在组件类中定义 setter

或者使用 datasetJSON.stringify 等技巧。


六、学习建议 & 下一步

✅ 适合学 Web Components 的人:

  • 想写可复用 UI 组件的开发者
  • 需要跨框架(React/Vue/Angular)共享组件的团队
  • 喜欢“少依赖、原生优先”理念的人

🚫 不适合的情况:

  • 你要开发一个复杂的 SPA(单页应用)
  • 团队已深度使用 React/Vue,没必要重复造轮子

🔜 接下来你可以:

  1. 尝试封装一个 <my-alert message="Hello"> 组件
  2. 学习 Lit —— 一个轻量库,让 Web Components 开发更简单(类似 React 的语法糖)
  3. 查看 MDN Web Components 文档

结语

Web Components 不是银弹,但它给了我们一种不依赖框架也能组件化的新思路。我当初学它,就是因为它让我意识到:很多看似“高级”的功能,其实浏览器早就原生支持了。

希望这篇教程能帮你迈出第一步。记住:最好的学习方式,就是动手写代码。 现在就去试试吧!

作者:一名爱讲人话的后端工程师
字数:2357(刚好达标 😄)

评论 0

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