---
url: 'https://dxpr.com/zh-hans/hc/documentation/learn-dxpr-builder/development/custom-elements'
title: '创建自定义元素 | DXPR'
author:
  name: Jurriaan
  url: 'https://dxpr.com/users/jurriaan'
date: '2026-10-24T00:45:39+00:00'
updated: '2026-10-24T09:09:48+00:00'
copyright: 'Copyright DXPR. All rights reserved.'
type: article
summary: |-
  每个 DXPR Builder 元素是推入 window.dxprBuilder.dxpr_elements 的 JavaScript 对象。编辑器将每个对象变成元素类，Style 和 Animation 选项卡已挂好。本页展示自带元素在 dxpr_builder/dxpr_elements.js 中如何定义、模块如何向编辑器添加自己的定义，以及生成的 HTML 什么样。元素没有服务器端 Twig 模板；元素在浏览器中渲染。
  编辑器如何注册元素
  编辑器按以下顺序加载六个脚本，由 dxpr_builder_library_info_build()（dxpr_builder.module 中的）定义为 dxpr_builder/editor.builder 库：
tags:
  - 'Bouw erop voort'
image: 'https://dxpr.com/themes/custom/dxpr_com/images/dxpr-share-card.jpg'
published: true
og:
  site_name: DXPR
  updated_time: '2026-10-24T09:09:48+0000'
  'image:alt': 'DXPR, powered by Drupal: AI-powered Drupal for marketers.'
schema:
  '@context': 'https://schema.org'
  '@graph':
    -
      mainEntity: {  }
    -
      '@type': TechArticle
      headline: 创建自定义元素
      description: |-
        每个 DXPR Builder 元素是推入 window.dxprBuilder.dxpr_elements 的 JavaScript 对象。编辑器将每个对象变成元素类，Style 和 Animation 选项卡已挂好。本页展示自带元素在 dxpr_builder/dxpr_elements.js 中如何定义、模块如何向编辑器添加自己的定义，以及生成的 HTML 什么样。元素没有服务器端 Twig 模板；元素在浏览器中渲染。
        编辑器如何注册元素
        编辑器按以下顺序加载六个脚本，由 dxpr_builder_library_info_build()（dxpr_builder.module 中的）定义为 dxpr_builder/editor.builder 库：
      image:
        '@type': ImageObject
        url: 'https://dxpr.com/themes/custom/dxpr_com/images/dxpr-share-card.jpg'
        width: '1200'
        height: '630'
      datePublished: '2026-10-24T00:45:39+0000'
      dateModified: '2026-10-24T09:09:48+0000'
      author:
        '@type': Organization
        '@id': 'https://dxpr.com/#organization'
        name: DXPR
        url: 'https://dxpr.com/'
        logo:
          '@type': ImageObject
          url: 'https://dxpr.com/themes/custom/dxpr_com/dxpr-logo-dark.svg'
          width: '1348'
          height: '501'
      publisher:
        '@type': Organization
        '@id': 'https://dxpr.com/#organization'
        name: DXPR
        url: 'https://dxpr.com/'
        logo:
          '@type': ImageObject
          url: 'https://dxpr.com/themes/custom/dxpr_com/dxpr-logo-dark.svg'
          width: '1348'
          height: '501'
      mainEntityOfPage: 'https://dxpr.com/zh-hans/hc/documentation/learn-dxpr-builder/development/custom-elements'
      articleSection: 'Bouw erop voort'
    -
      '@type': WebPage
      '@id': 'https://dxpr.com/zh-hans/hc/documentation/learn-dxpr-builder/development/custom-elements'
      description: |-
        每个 DXPR Builder 元素是推入 window.dxprBuilder.dxpr_elements 的 JavaScript 对象。编辑器将每个对象变成元素类，Style 和 Animation 选项卡已挂好。本页展示自带元素在 dxpr_builder/dxpr_elements.js 中如何定义、模块如何向编辑器添加自己的定义，以及生成的 HTML 什么样。元素没有服务器端 Twig 模板；元素在浏览器中渲染。
        编辑器如何注册元素
        编辑器按以下顺序加载六个脚本，由 dxpr_builder_library_info_build()（dxpr_builder.module 中的）定义为 dxpr_builder/editor.builder 库：
      breadcrumb:
        '@type': BreadcrumbList
        itemListElement:
          -
            '@type': ListItem
            position: 1
            name: 首页
            item: 'https://dxpr.com/zh-hans'
      publisher:
        '@type': Organization
        '@id': 'https://dxpr.com/#organization'
        name: DXPR
      inLanguage: zh-hans
---
[Help Center](/zh-hans/node/75)/[Documentation](/zh-hans/hc/documentation) /[Learn DXPR Builder](/hc/documentation/learn-dxpr-builder) /[Extend](/hc/documentation/learn-dxpr-builder/extend) /[Bouw erop voort](/hc/documentation/learn-dxpr-builder/extend/build-on-it) # 创建自定义元素.

 Learn DXPR BuilderExtendBouw erop voort

   ## In this guide

 Related guides

- [Hooks API 参考](/zh-hans/hc/documentation/learn-dxpr-builder/development/hooks-api)
- [架构](/zh-hans/hc/documentation/learn-dxpr-builder/development/architecture)

每个 DXPR Builder 元素是推入 `window.dxprBuilder.dxpr_elements` 的 JavaScript 对象。编辑器将每个对象变成元素类，Style 和 Animation 选项卡已挂好。本页展示自带元素在 `dxpr_builder/dxpr_elements.js` 中如何定义、模块如何向编辑器添加自己的定义，以及生成的 HTML 什么样。元素没有服务器端 Twig 模板；元素在浏览器中渲染。

## 编辑器如何注册元素

编辑器按以下顺序加载六个脚本，由 `dxpr_builder_library_info_build()`（`dxpr_builder.module` 中的）定义为 `dxpr_builder/editor.builder` 库：

1. `dxpr_templates.js`：从 `dxpr_builder/templates/` 编译的客户端 twig.js 模板。
2. `dxpr_global.js`：共享辅助函数和 CKEditor 5 集成。
3. `dxpr_events.js`
4. `dxpr_param_types.js`：向 `window.dxprBuilder.dxpr_param_types` 推入每种输入类型一个对象。
5. `dxpr_elements.js`：创建 `window.dxprBuilder.dxpr_elements` 数组并推入每个元素一个定义。
6. `dxpr_builder.js`：编辑器。该文件执行时调用 `create_dxpr_elements()`，遍历 `window.dxprBuilder.dxpr_elements` 并对每个定义：
    - 调用 `register_animated_element(base, is_container, Class)`，让类继承 `AnimatedElement`（Style 选项卡、Animation 选项卡、HTML ID、HTML 类和位置参数）；
    - 将继承的参数追加到定义的 `params`；
    - 通过 `make_param_type()` 转换每个参数，它将 `param.type` 与已注册的参数类型匹配；
    - 将定义的属性混入类原型。

因此定义必须在 `dxpr_elements.js` 运行后、`dxpr_builder.js` 运行前进入数组。六个文件都带 `defer` 属性加载，因此 script 标签的文档顺序即执行顺序。

## 元素定义

这是 `dxpr_builder/dxpr_elements.js` 中的 Alert 元素（源码：`dxpr_builder/build/dxpr-elements/elements/az_alert.js`），精简到每个元素都需要的属性。原件还设置了 `el_class`、`onCancel` 处理器和 `focusout` 监听器。

```javascript
window.dxprBuilder.dxpr_elements.push({
  base: "az_alert",
  name: Drupal.t("Alert"),
  nameEn: "Alert",
  icon: "az-custom-icon az-alert-icon",
  largeSettingsWindow: true,
  hidden: false,
  params: [
    {
      type: "textarea",
      heading: Drupal.t("Message"),
      param_name: "content",
      value: Drupal.t(
        "This is a placeholder text. Your actual content will go here. Edit this to include your own information.",
      ),
    },
    {
      type: "dropdown",
      heading: Drupal.t("Type"),
      param_name: "type",
      description: Drupal.t("Select message type."),
      getText: (opt) => opt.text,
      getValue: (opt) => opt.value,
      getDefault: (param) => param.value["alert-success"].value,
      value: {
        "alert-success": { text: Drupal.t("Success"), value: "alert-success" },
        "alert-info": { text: Drupal.t("Info"), value: "alert-info" },
        "alert-warning": { text: Drupal.t("Warning"), value: "alert-warning" },
        "alert-danger": { text: Drupal.t("Danger"), value: "alert-danger" },
      },
      passthrough: true,
    },
  ],
  show_settings_on_create: true,
  has_content: true,
  render(...args) {
    const state = {
      class: `az-element az-alert alert ${this.attrs.type} ${this.get_el_classes()} ${this.get_content_classes()}`,
      style: this.attrs.style,
      message: this.attrs.content,
    };
    this.dom_element = this.baseclass.prototype.render_template(
      "elements/alert/alert",
      state,
    );
    this.baseclass.prototype.render.apply(this, args);
  },
  save_history() {
    const container = this.get_my_container();
    container.save_container_history(Drupal.t("Edit alert"));
  },
});

```

| 属性 | 用途 |
|---|---|
| `base` | 机器名。它以 `data-azb="az_alert"` 写入已保存 HTML，页面重新解析时用于找到类。保留 `az_` 前缀。 |
| `name`、`nameEn` | 元素选择器中的标签及其未翻译形式。 |
| `icon` | 选择器图标的 CSS 类。自带图标定义在 `dxpr_builder/sass/dxpr-builder-backend/components/_custom-icons.scss` 中；自定义元素需要为自己的图标类写 CSS。 |
| `category` | 选择器选项卡。布局元素用 `Drupal.t("Layout")`；区块和视图用 `"CMS"`。默认内容选项卡请省略。 |
| `is_container` | `true`（元素容纳其他元素时）。 |
| `largeSettingsWindow` | 以较大尺寸打开设置对话框。 |
| `hidden` | 在选择器中隐藏元素，但保持可渲染。 |
| `params` | 对话框中显示的设置。见下文。 |
| `show_settings_on_create` | 元素放下后立即打开设置对话框。 |
| `has_content` | 元素有可编辑内容区（`dom_content_element`）。 |
| `render(...args)` | 构建 `this.dom_element`（从 `this.attrs`），再调用基础 `render`。 |
| `save_history()` | 推入带标签的撤销条目。 |
| `parse_attrs_from_dom(element)` | 可选。从已保存标记中读回参数值，与 `skip_data_azb` 和 `skip_params` 配合，供 Image 等将值存放在 `<img>` 属性而不是 `data-azat-*` 中的元素使用。 |

### 参数

每个 `params` 条目有：

| 键 | 含义 |
|---|---|
| `type` | 已注册的参数类型之一（下一节）。 |
| `heading` | 字段标签。 |
| `param_name` | 键在 `this.attrs` 中，在已保存 HTML 中是 `data-azat-<param_name>` 属性。`content` 特殊：它是元素正文，不是属性。 |
| `value` | 默认值。对 `dropdown` 是带 `getText`、`getValue` 和 `getDefault` 回调的选项对象。 |
| `description` | 字段下的帮助文本。 |
| `tab` | 将字段分组到命名折叠中，例如 `Drupal.t("SEO")`。 |
| `can_be_empty` | 存放空字符串，而不是丢弃属性。 |
| `safe` | 跳过存放值的 URL 编码。 |

参数类型是推入的 `type` 值，推到 `window.dxprBuilder.dxpr_param_types`（`dxpr_builder/dxpr_param_types.js` 中）：`boxmodel`、`checkbox`、`checkboxes`、`colorpicker`、`datetime`、`dropdown`、`dxb_slider`、`html`、`icon`、`image`、`images`、`link`、`links`、`numericfield`、`row_layout`、`saved_datetime`、`social_links`、`textarea`、`textfield` 和 `video`。未注册的类型回退到普通文本输入框（`BaseParamType`）。

不要重复使用每个元素继承的 `param_name`，例如 `color`、`background`、`el_class`、`hash` 或 `an_*` 动画名。Style 选项卡已拥有 `color`，因此同名的第二个参数从不写入 `data-azat-color`。

### 保存的内容

`update_data()`（`dxpr_builder.js` 中的）将元素写为 HTML：

- `data-azb="<base>"`（根元素上）；
- `data-azat-<param_name>="<value>"` 写入每个值与默认值不同的参数，URL 编码，除非参数设置了 `safe: true`；
- Style 选项卡的参数写为内联 `style` 和类，从不写为 `data-azat-*` 属性；
- `data-azcnt="true"`（设置了 `has_content` 时，在内容元素上）。

没有编辑器的访客收到去掉 `data-az*` 属性的 HTML：`DxprBuilderService::parseDocumentForCleanup()` 剥离它们，只在动画元素和 Carousel 等内置动态元素上保留固定列表。如果元素需要访客端 JavaScript 或 CSS，请在根元素上放 `data-dxpr-builder-libraries="<key>"` 属性：`parseDocumentForTemplateLibrary()` 为每个不带斜杠的键附加 `dxpr_builder/elements.<key>`。键是 `elements.*` 库（`dxpr_builder.libraries.yml` 中的）；带斜杠的键只在它是已注册图标集的 `library` 时有效。

## 最小可用示例

示例添加渲染带颜色段落的“Notice”元素。它直接构建 DOM，因为 `dxpr_templates.js` 中编译的 twig.js 模板是编辑器包的一部分，别的模块无法扩展。

1. 创建 `mymodule/js/notice-element.js`：

    ```javascript
    window.dxprBuilder.dxpr_elements.push({
      base: "az_notice",
      name: Drupal.t("Notice"),
      nameEn: "Notice",
      icon: "az-custom-icon az-alert-icon",
      params: [
        {
          type: "textfield",
          heading: Drupal.t("Text"),
          param_name: "text",
          value: Drupal.t("Notice text"),
        },
        {
          type: "colorpicker",
          heading: Drupal.t("Colour"),
          param_name: "notice_color",
          value: "#0d6efd",
        },
      ],
      show_settings_on_create: true,
      render(...args) {
        const el = document.createElement("div");
        el.className = `az-element az-notice ${this.get_el_classes()}`;
        if (this.attrs.style) {
          el.setAttribute("style", this.attrs.style);
        }
        const p = document.createElement("p");
        p.style.color = this.attrs.notice_color;
        p.textContent = this.attrs.text;
        el.appendChild(p);
        this.dom_element = el;
        this.baseclass.prototype.render.apply(this, args);
      },
      save_history() {
        this.get_my_container().save_container_history(Drupal.t("Edit notice"));
      },
    });

    ```
2. 将文件插入 `dxpr_elements.js`（权重 `-4`）与 `dxpr_builder.js`（权重 `-3`）之间的编辑器库（在 `mymodule.module` 中）：

    ```php
    /**
     * Implements hook_library_info_alter().
     */
    function mymodule_library_info_alter(array &$libraries, string $extension): void {
      if ($extension === 'dxpr_builder' && isset($libraries['editor.builder'])) {
        $path = '/' . \Drupal::service('extension.list.module')->getPath('mymodule');
        $libraries['editor.builder']['js'][$path . '/js/notice-element.js'] = [
          'weight' => -3.5,
          'preprocess' => FALSE,
          'attributes' => ['defer' => TRUE],
        ];
      }
    }

    ```

    `preprocess: FALSE` 和 `defer` 与模块为自己文件定义的条目一致，因此无论编辑器资源来自 CDN 还是本地构建，文件在序列中的位置不变。
3. 清除缓存并打开构建器页面：

    ```bash
    drush cr

    ```
4. 从选择器添加元素，设置文本和颜色并保存。字段存放：

    ```html
    <div class="az-element az-notice" id="..." data-azb="az_notice"
         data-azat-text="Hello" data-azat-notice_color="%23198754">
      <p style="color: #198754;">Hello</p>
    </div>

    ```

    访客得到去掉 `data-az*` 属性的同样标记。段落保留内联颜色，因此该元素不需要访客库。

## 要知道的限制

- **档案不列出自定义元素。** 构建器档案中的元素清单来自 `src/Form/DxprBuilderProfileForm.php` 和 `src/Service/Handler/ProfileHandler.php` 中的固定列表。该列表外的元素从不受档案隐藏。
- **选择器的图标**需要模块的 CSS；构建器自带的 `az-custom-icon` 类只覆盖自带元素。
- **`DxprBuilderService::getDxprElementsFolders()`** 及其 `hook_dxpr_builder_elements_folders_alter()` 返回主题中 `elements` 文件夹的列表，但编辑器中没有任何东西读该列表。它不是注册路线。
- **Style 和 Animation 选项卡**由 `register_animated_element()` 为您添加；不要重定义这些参数。

## 接下来做什么？

- [Hooks API](/zh-hans/hc/documentation/learn-dxpr-builder/development/hooks-api)：添加实用类和图标集的 PHP 钩子。
- [架构](/zh-hans/hc/documentation/learn-dxpr-builder/development/architecture)：编辑器与字段格式化器的配合。