使用原生 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 与主流框架之间的兼容性问题。

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

相关推荐
鱼樱前端5 分钟前
重度Cursor用户 最强 Cursor Rules 和 Cursor 配置 mcp 以及最佳实践配置方式
前端
曼陀罗6 分钟前
Path<T> 、 keyof T 什么情况下用合适
前端
锈儿海老师12 分钟前
AST 工具大PK!Biome 的 GritQL 插件 vs. ast-grep,谁是你的菜?
前端·javascript·eslint
飞龙AI14 分钟前
鸿蒙Next实现瀑布流布局
前端
快起来别睡了15 分钟前
代理模式:送花风波
前端·javascript·架构
海底火旺17 分钟前
电影应用开发:从代码细节到用户体验优化
前端·css·html
陈随易26 分钟前
Gitea v1.24.0发布,自建github神器
前端·后端·程序员
前端付豪29 分钟前
汇丰银行技术架构揭秘:全球交易稳定背后的“微服务+容灾+零信任安全体系”
前端·后端·架构
邹荣乐31 分钟前
uni-app开发微信小程序的报错[渲染层错误]排查及解决
前端·微信小程序·uni-app
今天出摊吗32 分钟前
表单元素的默认提交行为
前端