使用原生 JavaScript 实现组件化开发

说明

我们将通过实现一个名为 custom-card 的组件来展示如何使用浏览器提供的 customElements API 来创建自定义元素。


自定义组件详解

1. 创建组件

要创建一个自定义组件,需要继承 HTMLElement 类,并实现其功能。我们还将使用 Shadow DOM 来隔离组件内部的结构和样式。

⚠️ 注意:Shadow DOM 并不是所有元素都能添加(例如 <img> 标签无法添加伪类),这点需要注意。

js 复制代码
class CustomCard extends HTMLElement {
  constructor() {
    super();
    // 创建 Shadow DOM
    this.attachShadow({ mode: 'open' });
    
    // 获取模板并克隆插入到 Shadow DOM 中
    const template = document.querySelector('#custom-card-template');
    this.shadowRoot.appendChild(template.content.cloneNode(true));
  }
}

// 注册组件
customElements.define('custom-card', CustomCard);

2. 准备组件模板

我们使用 <template> 标签来存放组件的 HTML 模板。该标签默认不会渲染在页面上,但可以通过 JavaScript 访问其中的内容。

在样式部分,:host 是一个伪类选择器,用于选中 Shadow DOM 的根节点,即组件本身。

html 复制代码
<template id="custom-card-template">
  <style>
    :host {
      border: 1px solid #ccc;
      box-shadow: 0 2px 4px #ccc;
    }
    .card-head {
      border-bottom: 1px solid #ccc;
      padding: 6px 8px;
    }
    .card-foot {
      padding: 6px 8px;
      border-top: 1px solid #ccc;
    }
  </style>
  <div class="card-wraaper">
    <div class="card-head">
      <slot name="head">这是头部</slot>
    </div>
    <div class="card-body">
      <slot>这是中间的内容</slot>
    </div>
  </div>
</template>

3. 使用组件

在 HTML 页面中直接使用自定义标签 <custom-card> 即可:

  • 具名插槽(Named Slot) :通过 slot="xxx" 将内容插入指定名称的插槽。
  • 默认插槽(Default Slot) :未命名的内容将插入默认插槽。
  • 如果没有提供对应插槽的内容,则显示模板中的默认内容。
html 复制代码
<custom-card>
  <div slot="head">卡片1</div>
  <div>这是中间的内容1</div>
  <div>这是中间的内容2</div>
  <div>这是中间的内容3</div>
</custom-card>

补充知识与总结

以下是一些扩展知识点,帮助你更好地理解和使用 Web Components 技术。

组件生命周期方法

在定义组件类时,可以重写以下生命周期钩子函数:

方法名 触发时机
connectedCallback() 当组件被插入文档时调用
disconnectedCallback() 当组件从文档中移除时调用
attributeChangedCallback(attrName, oldVal, newVal) 当组件属性发生变化时调用(需配合 observedAttributes

📌 提示:如果希望监听某些属性的变化,必须在类中定义静态属性 observedAttributes,返回一个包含这些属性名的数组。


HTML 相关知识

  1. <template>:语义为模板,不直接渲染,常用于存储可重复使用的 HTML 片段。
  2. <slot>:插槽机制,允许外部传入内容填充组件模板。
  3. part标签属性:用于 Shadow DOM 中标记特定部分,可通过 CSS 选择器访问。
  4. is="custom-element"标签属性:可以在原生标签中使用自定义组件的行为。

CSS 相关知识

选择器 功能说明
::slotted() 选择插槽中的内容,如 ::slotted(.card-head)
:host 选择 Shadow DOM 的根节点
:defined 选择已经定义的自定义元素
::part(name) 选择具有 part="name" 的 Shadow DOM 子元素

JavaScript 相关知识

  1. window.customElements:用于注册自定义元素。
  2. Element.attachShadow():创建一个隔离的 Shadow DOM 结构,实现样式和 DOM 隔离。

与 Vue 等框架是否冲突?

可能会有人担心:使用 Web Components 是否会与 Vue、React 等框架产生冲突或难以辨识?

实际上,Vue 等框架在构建阶段会将组件编译成普通的 HTML 标签和 render 函数,最终生成的是标准的 DOM 元素。浏览器接收到的是标准标签,因此 Web Components 和框架之间并不会冲突。

如果你感兴趣,可以阅读官方文档了解更多信息: 🔗Vue 与 Web Components | Vue.js


总结

通过本文,你应该已经掌握了:

  • 如何使用原生 JavaScript 创建自定义组件;
  • 如何利用 Shadow DOM 实现样式和结构的封装;
  • 插槽机制的基本使用;
  • 生命周期方法的作用;
  • 以及 Web Components 与主流框架之间的兼容性问题。

加油,虽然是用不太上的知识点!

相关推荐
Cao_Ron4 分钟前
用 SVG image symbol 画 ECharts graph 圆形节点
前端
hxy06018 分钟前
React-Call让你的React组件像异步函数一样调用
前端·react.js
Hilaku9 分钟前
为什么 AI 写前端时,总是优先选择 React,而不是 Vue?
前端·javascript·程序员
京东云开发者11 分钟前
GPT-5.6、ChatGPT Work 与 Codex 更新食用指南
前端
Cao_Ron22 分钟前
用 ECharts graph 画出卡片式矩形节点
前端
skiyee31 分钟前
换个底座的 Wot Starter 居然让 AI 更懂项目!
前端·ai编程
anyup37 分钟前
这一套绝了!AI 大模型写故事,星云 SDK 驱动 3D 数字人实时演绎
前端·人工智能·aigc
耀耀切克闹灬1 小时前
短链跳转
前端
孟陬1 小时前
高质量全方位的 AI 工具 sse-stuntman — Mock SSE 接口
前端·node.js·openai
Cao_Ron1 小时前
给 ECharts 6 graph 节点叠加角标:从原理到性能优化
前端