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

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

相关推荐
蓝胖子的多啦A梦18 小时前
ElementUI表格错位修复技巧
前端·css·vue.js·el-table表格错位
_OP_CHEN19 小时前
前端开发实战深度解析:(一)认识前端和 HTML 与开发环境的搭建
前端·vscode·html·web开发·前端开发
xiAo_Ju19 小时前
iOS一个Fancy UI的Tricky实现
前端·ios
H***997619 小时前
Vue深度学习实战
前端·javascript·vue.js
toooooop819 小时前
Vuex 中 state、mutations 和 actions 的原理和写法
前端·javascript·uni-app
y***866919 小时前
前端CSS-in-JS方案
前端·javascript·css
暖木生晖20 小时前
APIs之WEB API的基本认知是什么?
前端·dom·dom树·web apis
华仔啊20 小时前
你真的懂递归吗?没那么复杂,但也没那么简单
前端·javascript
火星数据-Tina20 小时前
低成本搭建体育数据中台:一套 API 如何同时支撑比分网与 App?
java·前端·websocket
yddddddy20 小时前
深入浅出前端路由:从概念到实战
前端