JavaScript Web Components 教程:构建可复用自定义组件

引言

Web Components 是一套由浏览器原生支持的 Web API,它允许开发者创建可重用、封装良好的定制 HTML 元素,从而实现组件化的前端开发模式。通过 Web Components ,我们可以定义新的、功能丰富的用户界面元素,并且它们可以像标准HTML元素一样在任何地方被轻易地使用和组合。本教程将带你入门 JavaScript Web Components 的世界,了解其核心概念并实战创建一个基本的自定义组件。

Web Components 组件体系

Web Components 主要由以下四个核心技术构成:

1. Custom Elements(自定义元素)

  • 允许开发者扩展HTML元素集合,通过定义新的标签来创建自定义组件。
javascript 复制代码
class MyCustomElement extends HTMLElement {
 constructor() {
   super();
   // 构造逻辑...
 }
 
 connectedCallback() {
   // 当 custom element首次被插入文档DOM时,被调用
 }
 
 disconnectedCallback() {
   // 当 custom element从文档DOM中删除时,被调用
 }
 
 adoptedCallback() {
   // 当 custom element被移动到新的文档时,被调用
 }
 
 attributeChangedCallback() {
   // 当 custom element增加、删除、修改自身属性时,被调用
 }
}
customElements.define('my-component', MyCustomElement);

2. Shadow DOM(影子DOM)

  • 提供了封装样式和结构的能力,使组件内部的CSS样式不会影响到外部环境,反之亦然。
javascript 复制代码
const shadowRoot = this.attachShadow({ mode: 'open' });
shadowRoot.innerHTML = `
 <style>
   /* 组件内部样式 */
 </style>
 <div class="content">...</div>
`;

3. HTML Templates(HTML模板)

  • 使用<template><slot>元素定义组件的内容和可替换区域。
html 复制代码
<template id="my-template">
  <style>
    /* 组件样式 */
  </style>
  <div class="container">
    <slot></slot> <!-- 这里可以插入其他元素 -->
  </div>
</template>

4. HTML Imports(已废弃,现推荐使用模块系统)

  • 原本用于导入HTML文件作为组件的载体,但在现代浏览器中,我们通常使用ES6模块或其他模块加载机制来引入组件脚本。

创建一个简单的 Web Component

下面,我们将一步步创建一个名为my-counter的基本计数器组件:

html 复制代码
<!-- my-counter.html -->
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>My Counter Web Component</title>
  <script type="module">
    class MyCounter extends HTMLElement {
      constructor() {
        super();
        this._count = 0;
        this.attachShadow({ mode: 'open' });
        this.shadowRoot.appendChild(this.createTemplate());
        this.incrementBtn = this.shadowRoot.querySelector('.increment');
        this.decrementBtn = this.shadowRoot.querySelector('.decrement');
        this.counterDisplay = this.shadowRoot.querySelector('#counter');
      }

      createTemplate() {
        const template = document.createElement('template');
        template.innerHTML = `
          <style>
            .counter-container {
              display: flex;
              align-items: center;
            }
            button {
              margin: 0 10px;
            }
          </style>
          <div class="counter-container">
            <button class="increment">+</button>
            <span id="counter">0</span>
            <button class="decrement">-</button>
          </div>
        `;
        return template.content.cloneNode(true);
      }

      connectedCallback() {
        this.incrementBtn.addEventListener('click', () => this.increment());
        this.decrementBtn.addEventListener('click', () => this.decrement());
      }

      increment() {
        this._count++;
        this.updateCount();
      }

      decrement() {
        if (this._count > 0) {
          this._count--;
          this.updateCount();
        }
      }

      updateCount() {
        this.counterDisplay.textContent = this._count;
      }
    }

    customElements.define('my-counter', MyCounter);
  </script>
</head>
<body>
  <my-counter></my-counter>
</body>
</html>

在这个例子中,我们定义了一个MyCounter类,它继承自HTMLElement并实现了构造函数、生命周期钩子以及一些方法来控制计数器的行为。组件内部使用了 Shadow DOM,并且包含两个按钮和一个显示计数值的<span>元素。

使用Web Components

现在你已经创建了一个 Web Component ,你可以像普通 HTML 元素那样在页面中使用它:

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Using My Counter Component</title>
  <link rel="import" href="my-counter.html"> <!-- 如果不使用模块,则通过链接引入 -->
</head>
<body>
  <h1>Counters:</h1>
  <my-counter></my-counter>
  <my-counter></my-counter>
</body>
</html>

写在最后

Web ComponentsWeb 开发带来了一种强大的组件化方式,让开发者能够更好地组织代码,提升代码复用性和维护性。通过深入学习和实践,你会发现 Web Components 在现代前端项目中的巨大价值。

喜欢的话帮忙点个赞 + 关注吧,将持续更新 JavaScript 相关的文章,还可以关注我的公众号 梁三石FE ,感谢您的关注~

相关推荐
好运的阿财36 分钟前
OpenClaw工具拆解之host_workspace_write+host_workspace_edit
前端·javascript·人工智能·机器学习·ai编程·openclaw·openclaw工具
XiYang-DING1 小时前
JavaScript
开发语言·javascript·ecmascript
空中海2 小时前
02 React Native状态、导航、数据流与设备能力
javascript·react native·react.js
空中海2 小时前
02 状态、Hooks、副作用与数据流
开发语言·javascript·ecmascript
空中海3 小时前
04 React Native工程化、质量、发布与生态选型
javascript·react native·react.js
杨超凡3 小时前
豆包收费了?我特么自己用“意念”搓了一个!
javascript
threelab4 小时前
Three.js 咖啡杯烟雾效果 | 三维可视化 / AI 提示词
开发语言·javascript·人工智能
Heo5 小时前
14_React 中的更新队列 updateQueue
前端·javascript·面试
前端 贾公子5 小时前
解决浏览器端 globalThis is not defined 报错
前端·javascript·vue.js