0Pricing
JavaScript Academy · 课时

定义自定义元素

使用 customElements API 注册元素。

定义自定义元素 是 CoddyKit 上的免费 JavaScript Academy 课时。 这是第 1 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 JavaScript Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 JavaScript Academy 课程共包含 4 节课。

什么是自定义元素

自定义元素让您可以定义由 JavaScript 类支持的自定义 HTML 标签。您无需将许多 div 拼凑在一起,而是可以创建类似 <user-card> 的可复用、自包含组件。

  • 它们属于 Web 组件标准。
  • 它们可以原生运行在浏览器中,无需框架。
  • 自定义元素名称必须包含连字符(例如 my-button)。

customElements 注册表

浏览器通过 window.customElements 提供一个全局注册表。调用 customElements.define(name, constructor) 即可注册新标签。

定义完成后,文档中所有匹配的标签都会升级为您所定义类的实例。

// Register a tag named 'hello-world'
customElements.define('hello-world', HelloWorld);

// After this, every <hello-world> in the page
// becomes an instance of the HelloWorld class.

扩展 HTMLElement

自定义元素是一个 extends HTMLElement 的类。基类会为您的元素提供所有标准 DOM 功能(属性、事件和样式)。

在构造函数中始终先调用 super(),以确保元素得到正确初始化。

class HelloWorld extends HTMLElement {
  constructor() {
    super(); // required, sets up the element
  }
}

customElements.define('hello-world', HelloWorld);

渲染内容

在元素内部,您可以设置 this.innerHTML,或使用 DOM 方法构建内容。一种常见模式是在元素连接到页面时进行渲染。

class HelloWorld extends HTMLElement {
  connectedCallback() {
    this.innerHTML = '<p>Hello from a custom element!</p>';
  }
}

customElements.define('hello-world', HelloWorld);

在 HTML 中使用元素

注册完成后,像使用任何内置元素一样使用您的标签。您可以直接将它放入标记中,也可以使用 document.createElement 创建它。

// In HTML:
// <hello-world></hello-world>

// Or in JavaScript:
const el = document.createElement('hello-world');
document.body.appendChild(el);

构造函数的规则

创建实例时会运行构造函数。这里有一些严格的规则:

  • 先调用 super()。
  • 不要在这里检查或添加属性和子元素。
  • 将 DOM 操作推迟到 connectedCallback 中。

构造函数只能用于设置初始状态和事件监听器。

class CounterButton extends HTMLElement {
  constructor() {
    super();
    this.count = 0; // safe: just internal state
  }
}

customElements.define('counter-button', CounterButton);

添加行为

由于您的元素是真实的 DOM 节点,因此您可以为它附加事件监听器,并根据交互更新其内容。

class CounterButton extends HTMLElement {
  constructor() {
    super();
    this.count = 0;
  }
  connectedCallback() {
    this.textContent = 'Clicked 0 times';
    this.addEventListener('click', () => {
      this.count++;
      this.textContent = 'Clicked ' + this.count + ' times';
    });
  }
}
customElements.define('counter-button', CounterButton);

连字符要求

自定义元素名称必须包含连字符。这可以确保它们不会与当前或未来的内置 HTML 元素冲突。

  • my-widget 有效。
  • mywidget 无效,会抛出错误。
  • 名称不区分大小写,但应使用小写书写。
// Valid:
customElements.define('app-header', AppHeader);

// Invalid - throws SyntaxError (no hyphen):
// customElements.define('appheader', AppHeader);

whenDefined 和 get

两个实用的注册表方法:

  • customElements.get(name) 返回构造函数;如果尚未注册,则返回 undefined。
  • customElements.whenDefined(name) 返回一个 Promise,在元素定义完成后解析。
customElements.whenDefined('hello-world').then(() => {
  console.log('hello-world is ready to use');
});

const Ctor = customElements.get('hello-world');

只能定义一次

每个名称只能注册一次。使用已占用的名称调用 define 会抛出错误。请在共享模块中防止重复注册。

if (!customElements.get('hello-world')) {
  customElements.define('hello-world', HelloWorld);
}

自定义元素为何重要

自定义元素为您提供与框架无关、封装且可复用的用户界面。它们可以:

  • 在任何技术栈中规范组件复用。
  • 与浏览器自身的生命周期集成。
  • 自然地与阴影 DOM 和模板配合使用(稍后介绍)。

快速检查

检验您对定义自定义元素的理解。

回顾

您已经学会了如何定义自定义元素:

  • customElements.define(name, class) 会注册一个标签。
  • 该类 extends HTMLElement,并首先调用 super()。
  • 名称必须包含连字符。
  • 请在 connectedCallback 中渲染内容,而不是在构造函数中渲染。
  • get 和 whenDefined 可以帮助您检查注册状态。

接下来,我们将探索自定义元素的完整生命周期。

常见问题解答

「定义自定义元素」课时是免费的吗?

是的 — 「定义自定义元素」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 JavaScript Academy 课程的其余内容,请升级到 CoddyKit PRO。 JavaScript Academy 课程共包含 4 节课。

「定义自定义元素」这节课中我会学到什么?

使用 customElements API 注册元素。 你通过在浏览器中直接运行的动手代码来练习 JavaScript Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 JavaScript Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 JavaScript Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 1 节课,共 4 节。

「定义自定义元素」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 JavaScript Academy 课中编写并运行代码吗?

能。每节 JavaScript Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. 定义自定义元素
  2. 生命周期回调
  3. Shadow DOM 与封装
  4. 模板与插槽
← 返回 JavaScript Academy