Web Components:原生组件化开发新趋势 —— 面向零基础初学者的教程

马秀英_技术达人
2025-06-16 16:27
阅读 361

一、开篇:什么是Web Components?它能用来做什么?

一、开篇:什么是Web Components?它能用来做什么?

你有没有想过,为什么在网页上看到一个按钮或输入框时,它们看起来都差不多,但背后却可能来自不同的框架?这是因为这些界面元素通常由HTML标签直接提供,比如 <button><input>

那如果我们想创造属于自己的 HTML 标签呢?例如写一个 <my-calendar><custom-header> 呢?这听起来像是天马行空的想法,但现实是:可以实现!而且不用任何框架(Vue、React等)也能做到。

这就是我们今天要讲的内容:Web Components(网络组件)

Web Components 是什么?

简单来说:

Web Components 就是一组浏览器原生支持的技术标准,允许你创建可复用、自定义的 HTML 元素。

它可以让你像编写普通 HTML 标签一样使用自己的组件。就像下面这样:

<my-counter></my-counter>

无需借助 Vue 或 React,只需要标准的 HTML/CSS/JS 就可以完成这个组件的定义和使用。

Web Components 有什么用?

  • ✅ 创建“自己定义”的 HTML 元素(如 <tabs><notification-box> 等)
  • 🔄 组件高度封装、可复用
  • 🔌 与任何前端框架兼容甚至无缝集成
  • 🧠 原生支持,无需依赖第三方库

二、环境准备:你需要做的第一步

二、环境准备:你需要做的第一步

作为初学者,不需要安装复杂的编辑器或框架,只要准备好最基础的工具即可:

所需工具清单:

  1. 一台电脑(Windows/Mac/Linux都可以)
  2. 任意文本编辑器:
    • 推荐:VS Code(免费、功能强大)
  3. 任意现代浏览器:
    • Chrome / Edge / Firefox / Safari 都支持 Web Components

项目结构建议(用于练习)

你可以建立如下简单的文件夹结构来开始学习:

web-components-demo/
│
├── index.html
├── main.js
└── style.css

示例代码初始化

打开 index.html 输入以下内容:

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8" />
    <title>Web Components 学习</title>
    <link rel="stylesheet" href="style.css">
</head>
<body>

<h1>欢迎来到 Web Components 教程</h1>

<!-- 待会我们将在这里放我们的自定义组件 -->

<script src="main.js" type="module"></script>
</body>
</html>

注意:我们使用了 type="module" 来引入 JS 模块,这是 Web Components 必须的基础。


三、核心概念详解(带代码示例)

三、核心概念详解(带代码示例)

Web Components 包括三项核心技术:

  1. 自定义元素(Custom Elements)
  2. Shadow DOM(影子DOM)
  3. HTML模板(Templates)

我们逐一讲解,并结合实例进行说明。


3.1 自定义元素(Custom Element)

我们可以使用 JavaScript 的 customElements.define() 方法来创建自己的 HTML 标签。

示例:创建一个叫 <hello-world> 的自定义标签

main.js 中添加以下代码:

class HelloWorld extends HTMLElement {
    constructor() {
        super();
        this.innerText = "Hello, 自定义组件!";
    }
}

customElements.define("hello-world", HelloWorld);

现在回到你的 HTML 文件中加入这个标签:

<hello-world></hello-world>

刷新页面看看效果吧!

💡 新手提醒

  • 类名必须以大写字母开头。
  • 调用 super() 是为了继承基本行为。
  • 元素名必须包含短横线(-),不能只是一个单词,比如 card 不合法,要用 my-card

3.2 使用 Shadow DOM 实现样式隔离

默认情况下,我们在主页面中的 CSS 可能会影响到自定义组件中的样式。为了让组件有更独立的样式空间,我们可以用 Shadow DOM。

示例:给 <hello-world> 加入 Shadow DOM

修改 main.js 如下:

class HelloWorld extends HTMLElement {
    constructor() {
        super();

        // 创建 Shadow Root
        const shadow = this.attachShadow({ mode: 'open' });

        // 创建一个 span 并插入到 Shadow DOM 中
        const span = document.createElement('span');
        span.textContent = "Hello from Shadow DOM!";
        span.style.color = "blue";

        shadow.appendChild(span);
    }
}

customElements.define("hello-world", HelloWorld);

此时,你在主页面写的外部 CSS 不会影响该组件内的样式!

总结一下 Shadow DOM 的优点:

  • 组件样式完全隔离
  • 避免 CSS 冲突
  • 更容易维护复杂项目

3.3 HTML Template 模板复用

如果我们要展示比较复杂的 HTML 结构,每次都通过 JS 动态创建节点就太麻烦了。这时候我们就可以用 <template> 标签来提前准备好结构。

示例:创建一个卡片组件 <user-card>

index.html 中添加:

<template id="user-card-template">
    <style>
        .card {
            border: 1px solid #ccc;
            padding: 10px;
            margin: 10px 0;
            max-width: 300px;
        }
        h2 { color: darkorange; }
    </style>
    <div class="card">
        <h2>用户名:李小明</h2>
        <p>用户年龄:25岁</p>
    </div>
</template>

然后在 main.js 中编写对应的组件类:

class UserCard extends HTMLElement {
    constructor() {
        super();
        const template = document.getElementById("user-card-template");
        const shadow = this.attachShadow({ mode: 'open' });
        shadow.appendChild(template.content.cloneNode(true));
    }
}

customElements.define("user-card", UserCard);

最后,在 HTML 页面中插入:

<user-card></user-card>

你就能看到一个完整风格的用户信息卡!


四、实战项目:做一个点击计数器组件 <click-counter>

四、实战项目:做一个点击计数器组件 <click-counter>

让我们动手来做一个完整的组件实践。

目标:每次点击按钮,数字 +1,显示在一个自定义元素中。

第一步:添加模板结构

index.html 中添加:

<template id="counter-template">
    <style>
        button {
            font-size: 16px;
            padding: 10px;
            cursor: pointer;
        }
        p {
            font-weight: bold;
        }
    </style>
    <button>点击我</button>
    <p>点击次数:<span>0</span></p>
</template>

第二步:定义组件逻辑

main.js 中添加:

class ClickCounter extends HTMLElement {
    constructor() {
        super();

        const template = document.getElementById("counter-template");
        const shadow = this.attachShadow({ mode: 'open' });
        const clone = template.content.cloneNode(true);

        this.shadowRoot = shadow;
        shadow.appendChild(clone);

        // 获取按钮和计数器 span
        this.button = shadow.querySelector("button");
        this.countSpan = shadow.querySelector("span");

        this.count = 0;

        // 添加点击事件
        this.button.addEventListener("click", () => {
            this.count++;
            this.countSpan.textContent = this.count;
        });
    }
}

customElements.define("click-counter", ClickCounter);

第三步:使用组件

在 HTML 中插入:

<click-counter></click-counter>

保存所有文件并刷新浏览器,你会看到一个可点击的计数器!


五、常见问题解答(FAQ)

问:Web Components 和 Vue/React 有什么区别?

答:

  • Vue/React 是成熟的框架,功能丰富,生态成熟;
  • Web Components 是浏览器原生特性,适合组件级别封装,不绑定于某一个技术栈;
  • Web Components 可以被任意框架使用,也可以与传统 HTML 结合。

问:为什么不推荐全局 CSS 影响我的组件?

答:
因为如果你的组件样式被其他页面影响了,那就不是真正的组件化。Shadow DOM 提供了样式隔离,保证了组件的健壮性和可移植性。

问:为什么自定义元素名称需要带短横线?

答:
这是一个规范(来自 WHATWG)。目的是避免未来与标准 HTML 元素冲突。例如,未来可能会出现 dialogmenu 这样的官方标签,而不会和我们自定义的名字重复。

问:能否将 Web Components 应用在旧浏览器中?

答:
主流现代浏览器(Chrome、Edge、Firefox、Safari)都已支持 Web Components,但对于 IE11 或更低版本浏览器,需要引入 polyfill 补丁。


六、下一步学习建议

恭喜你完成了第一个 Web Components 项目的构建!下面是一些进阶方向:

建议 1:掌握属性和事件传递

尝试让组件接受外部传入的数据:

<click-counter initial-count="5"></click-counter>

可以通过 attributeChangedCallback() 监听属性变化。

建议 2:了解自定义元素生命周期方法

常用的钩子函数包括:

方法 描述
constructor() 构造函数,最先执行
connectedCallback() 当组件插入页面时触发
disconnectedCallback() 移除组件时触发
adoptedCallback() 在文档之间移动时调用
attributeChangedCallback() 属性变化监听

建议 3:配合现有框架使用

虽然 Web Components 可以单独使用,但它也可以很好融入 Vue、React、Angular 等框架中。

例如在 React 中使用只需:

function App() {
    return (
        <div>
            <click-counter initial-count="10"></click-counter>
        </div>
    )
}

记得在入口文件中加载 Web Components!

建议 4:阅读文档和社区资源


总结

通过本教程,你学会了:

  • 什么是 Web Components
  • 如何搭建开发环境
  • 核心三大技术(自定义元素、Shadow DOM、Template)
  • 完成了一个点击计数器组件的实战
  • 解决了初学者常遇到的问题

你现在已经掌握了浏览器原生的组件开发方式,可以尝试创建更多实用的自定义组件,甚至发布分享给他人使用!

继续加油,成为真正懂“底层原理”的全栈开发者吧!🚀


如果你喜欢这份教程,请点赞、收藏并分享给其他正在学习编程的朋友。也欢迎留言告诉我你想看哪些前端相关的后续内容!

评论 0

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