JavaScript中如何创建自定义元素?

来源:个人站长网作者:IT小魔仙头衔:程序员
导读:本期聚焦于小伙伴创作的《JavaScript中如何创建自定义元素?》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《JavaScript中如何创建自定义元素?》有用,将其分享出去将是对创作者最好的鼓励。

JavaScript中创建自定义元素需要遵循Web Components规范中的Custom Elements相关规则,通过浏览器提供的原生API即可完成自定义元素的注册和使用,不需要依赖第三方框架。

JavaScript中如何创建自定义元素?

自定义元素的基础概念

自定义元素分为两类,一类是自主自定义元素,即完全独立的新元素,名称中必须包含短横线,比如<user-card>;另一类是自定义内置元素,继承自已有的原生HTML元素,比如继承自<button>的自定义按钮元素。

创建自定义元素的核心步骤是定义一个继承自HTMLElement的类,然后通过customElements.define方法将类注册为自定义元素。

自主自定义元素的创建步骤

1. 定义元素类

首先需要创建一个类,这个类必须继承自HTMLElement,我们可以在类的构造函数中初始化元素的内容、属性等。

// 定义自主自定义元素的类
class UserCard extends HTMLElement {
  constructor() {
    // 必须首先调用super(),继承HTMLElement的属性和方法
    super();
    // 初始化元素内容
    this.innerHTML = `
      <div class="user-card">
        <h3>默认用户名</h3>
        <p>默认用户简介</p>
      </div>
    `;
  }
}

2. 注册自定义元素

定义好类之后,需要使用customElements.define方法将类注册到浏览器中,第一个参数是自定义元素的标签名,必须包含短横线,第二个参数是对应的类。

// 注册自定义元素,标签名为user-card
customElements.define('user-card', UserCard);

3. 在页面中使用自定义元素

注册完成之后,就可以像使用原生HTML元素一样在页面中使用这个自定义元素了,既可以直接写在HTML中,也可以通过JavaScript动态创建。

<!-- 直接在HTML中使用 -->
<user-card></user-card>

<script>
  // 通过JavaScript动态创建
  const card = document.createElement('user-card');
  document.body.appendChild(card);
</script>

自定义元素的生命周期回调

自定义元素提供了多个生命周期回调函数,我们可以在对应的时机执行特定的逻辑:

  • connectedCallback:当元素被插入到DOM树中时触发,适合做初始化操作、添加事件监听等。
  • disconnectedCallback:当元素从DOM树中移除时触发,适合做清理操作,比如移除事件监听、清除定时器等。
  • attributeChangedCallback:当元素的被监听的属性发生变化时触发,需要配合静态属性observedAttributes使用。
  • adoptedCallback:当元素被移动到新的文档时触发,比如使用document.adoptNode方法时。

下面是一个使用生命周期回调的例子,实现当元素的name属性变化时更新显示内容:

class UserCard extends HTMLElement {
  // 定义需要监听的属性列表
  static get observedAttributes() {
    return ['name', 'intro'];
  }

  constructor() {
    super();
    this.innerHTML = `
      <div class="user-card">
        <h3 id="name"></h3>
        <p id="intro"></p>
      </div>
    `;
  }

  // 元素插入DOM时触发
  connectedCallback() {
    console.log('user-card元素被插入到DOM中');
    // 初始化属性内容
    this.updateContent();
  }

  // 监听的属性变化时触发
  attributeChangedCallback(name, oldValue, newValue) {
    console.log(`属性${name}从${oldValue}变为${newValue}`);
    this.updateContent();
  }

  // 元素从DOM移除时触发
  disconnectedCallback() {
    console.log('user-card元素从DOM中移除');
  }

  // 更新元素内容的公共方法
  updateContent() {
    const nameEl = this.querySelector('#name');
    const introEl = this.querySelector('#intro');
    if (nameEl) {
      nameEl.textContent = this.getAttribute('name') || '默认用户名';
    }
    if (introEl) {
      introEl.textContent = this.getAttribute('intro') || '默认用户简介';
    }
  }
}

// 注册元素
customElements.define('user-card', UserCard);

使用的时候可以通过设置属性来更新内容:

<user-card name="张三" intro="前端开发工程师"></user-card>

<script>
  const card = document.querySelector('user-card');
  // 修改属性,会触发attributeChangedCallback
  setTimeout(() => {
    card.setAttribute('name', '李四');
    card.setAttribute('intro', '后端开发工程师');
  }, 2000);
</script>

为自定义元素添加样式

自定义元素内部的样式可以通过两种方式添加,一种是直接在外部CSS中编写对应标签的样式,另一种是使用shadow DOM封装内部样式,避免外部样式污染。

方式一:外部CSS样式

直接在页面的CSS中写自定义元素的样式即可,和原生元素的样式写法一致。

/* 外部样式作用于user-card元素 */
user-card {
  display: block;
  width: 300px;
  border: 1px solid #ccc;
  padding: 16px;
  border-radius: 8px;
}

user-card h3 {
  color: #333;
  margin: 0 0 8px 0;
}

user-card p {
  color: #666;
  margin: 0;
}

方式二:使用Shadow DOM封装样式

在构造函数中创建Shadow DOM,将元素内容放在Shadow DOM内部,内部的样式只作用于Shadow DOM内部,不会影响到外部。

class UserCard extends HTMLElement {
  constructor() {
    super();
    // 创建开放模式的Shadow DOM
    const shadow = this.attachShadow({ mode: 'open' });
    // Shadow DOM内部的内容
    shadow.innerHTML = `
      <style>
        /* 样式只作用于Shadow DOM内部 */
        .container {
          width: 300px;
          border: 1px solid #ccc;
          padding: 16px;
          border-radius: 8px;
        }
        h3 {
          color: #333;
          margin: 0 0 8px 0;
        }
        p {
          color: #666;
          margin: 0;
        }
      </style>
      <div class="container">
        <h3>默认用户名</h3>
        <p>默认用户简介</p>
      </div>
    `;
  }
}

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

自定义内置元素的创建

如果需要继承自已有的原生元素,比如创建一个带计数功能的<button>,可以创建自定义内置元素,定义类的时候继承对应的原生元素类,注册的时候传入第三个参数指定继承的原生元素。

// 继承HTMLButtonElement
class CountButton extends HTMLButtonElement {
  constructor() {
    super();
    this.count = 0;
    this.textContent = `点击次数:${this.count}`;
    // 添加点击事件
    this.addEventListener('click', () => {
      this.count++;
      this.textContent = `点击次数:${this.count}`;
    });
  }
}

// 注册自定义内置元素,第三个参数指定继承的原生元素
customElements.define('count-button', CountButton, { extends: 'button' });

使用自定义内置元素的时候需要指定is属性:

<button is="count-button"></button>

注意事项

  • 自定义元素的标签名必须包含至少一个短横线,否则注册的时候会报错。
  • 自定义元素的类必须继承自HTMLElement或者对应的原生元素类,构造函数中必须首先调用super()
  • customElements.define必须在自定义元素被创建之前调用,否则浏览器会将其当作未知元素处理。
  • 如果需要监听属性变化,必须定义静态属性observedAttributes,返回需要监听的属性名数组,否则attributeChangedCallback不会触发。
  • 自定义元素目前主流现代浏览器都已经支持,如果需要兼容旧版本浏览器,需要引入对应的polyfill。

JavaScript自定义元素Custom_ElementsWeb_Components修改时间:2026-07-21 02:39:37

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。