Elementor Atomic Builder 变量类型扩展实战从 PHP 类型注册到编辑器registerVariableType的完整链路【免费下载链接】elementorThe most advanced frontend drag drop page builder. Create high-end, pixel perfect websites at record speeds. Any theme, any page, any design.项目地址: https://gitcode.com/GitHub_Trending/el/elementor本文以 Elementor 开源仓库的 extend-variables.md 示例文档为主线系统讲解如何为 Elementor Atomic Builder 的变量Design Tokens / Kit Tokens系统注册一种全新的变量类型如 shadow、gradient stop 等。读者将掌握完整四层扩展链路PHP 变量类型注册elementor/variables/register、Style Schema 联合类型扩充elementor/atomic-widgets/styles/schema、PHP 渲染 Transformer 注册elementor/atomic-widgets/styles/transformers/register以及编辑器端registerVariableType的 JS 注册并理解 REST / MCP 接口如何与已注册类型联动。一、扩展前的全局认知变量类型的四层契约在动手写代码之前需要先理解 Elementor 的变量系统modules/variables/把一种变量类型拆成了四层独立契约缺一不可层职责关键入口PHP 类型注册定义类型 key 与 PropType驱动校验、存储、Schema 联合、渲染elementor/variables/registeraction触发于 WordPressinitStyle Schema 联合把$$type变量并入各样式属性的联合类型使编辑器/校验器接受该类型elementor/atomic-widgets/styles/schemafilterPHP 渲染 Transformer前端渲染时把变量 id 解析为var(--label)等 CSS 输出elementor/atomic-widgets/styles/transformers/registeractionJS 编辑器注册让变量出现在 Add Variable 下拉、提供图标、值编辑器与样式转换器registerVariableType()editor v2 包的init()中调用从源码结构看这种分层设计是有意为之Variable_Types_Registry只是维护key → Transformable_Prop_Type实例的映射见 variable-types-registry.php而每个变量类型真正发挥作用必须分别接入 schema 校验、CSS 输出和编辑器 UI。前置条件变量模块Module::MODULE_NAME e-variables只有在Atomic Widgets 实验e_atomic_elements激活时才加载——见 module.php 中的is_experiment_active()检查其实验名来自Elementor\Modules\AtomicWidgets\Module::EXPERIMENT_NAME。因此扩展变量类型前请确保该实验已在站点中开启否则elementor/variables/register等钩子根本不会触发。二、PHP 层注册变量类型注册监听器必须在 WordPressinit之前挂载——因为Module::init_variable_types_registry()挂在init钩子上会创建注册表实例并立刻do_action( elementor/variables/register, $registry )之后才轮到你的回调。对应源码// modules/variables/module.php节选 add_action( init, [ $this, init_variable_types_registry ] ); public function init_variable_types_registry(): void { $this-variable_types_registry new Variable_Types_Registry(); do_action( elementor/variables/register, $this-variable_types_registry ); }注册自定义类型的标准写法以 shadow 变量为例add_action( elementor/variables/register, function ( \Elementor\Modules\Variables\Classes\Variable_Types_Registry $registry ) { $registry-register( \My\Shadow_Variable_Prop_Type::get_key(), \My\Shadow_Variable_Prop_Type::make() ); } );Variable_Types_Registry的公开 API 非常简单见 variable-types-registry.php方法签名作用register()register( string $key, Transformable_Prop_Type $prop_type ): void将类型 key 映射到 PropType 实例get()get( $key )按 key 查询单个类型不存在返回nullall()all(): array返回全部已注册类型内置类型 key闭源列表的参照系仓库内置类型在 hooks.php 的register_variable_types()中注册这是扩展新类型时最直接的参照$registry-register( Color_Variable_Prop_Type::get_key(), new Color_Variable_Prop_Type() ); $registry-register( Font_Variable_Prop_Type::get_key(), new Font_Variable_Prop_Type() ); $registry-register( Prop_Type_Adapter::GLOBAL_CUSTOM_SIZE_VARIABLE_KEY, new Size_Variable_Prop_Type() ); $registry-register( Size_Variable_Prop_Type::get_key(), new Size_Variable_Prop_Type() );对应的内置 key 为global-color-variable、global-font-variable、global-size-variable、global-custom-size-variable。其中前两者分别定义于 color-variable-prop-type.php 与font-variable-prop-type.php都是继承String_Prop_Type并覆盖get_key()global-custom-size-variable是global-size-variable的别名常量定义于Adapters\Prop_Type_Adapter。自定义类型同样应该继承String_Prop_Type或其子类并实现get_key()静态方法这样make()工厂、validate()等基础能力即可复用。三、Style Schema 联合让原子样式键接受你的$$type仅注册 PHP 类型还不够——Atomic Widgets 的每个样式属性都有严格的 Schema通常是Union_Prop_Type必须把新类型并入联合编辑器与校验器才会接受该属性可以引用这种变量。这一步通过 filter 完成add_filter( elementor/atomic-widgets/styles/schema, function ( array $schema ) { // Add your variable $$type to the union for relevant style keys. return $schema; } );仓库内置实现给出了两种可镜像的模板style-schema.php针对颜色与字体。它会遍历整个 schema对每个Color_Prop_Type执行Union_Prop_Type::create_from( $color_prop_type )-add_prop_type( Color_Variable_Prop_Type::make() )对font-family键额外把Font_Variable_Prop_Type并入联合同时递归处理Union_Prop_Type、Object_Prop_Type合并 shape、Array_Prop_Type更新 item type。size-style-schema.php针对尺寸且带有更细的门控逻辑——Size_Style_Schema会跳过可用单位为角度angle与时间time的属性units_to_skip取自Size_Constants::angle()与Size_Constants::time()因为对这类属性注入变量没有意义此外Grid_Track_Size_Prop_Type仅在Elementor Pro ≥ 4.2时才并入 size 变量is_grid_track_variables_supported_by_pro()同时检查ElementorUtils::has_pro()与ELEMENTOR_PRO_VERSION。你自己的 filter 回调里建议参照Style_Schema的做法根据目标属性现有的 PropType 类别Color_Prop_Type/String_Prop_Type/Union_Prop_Type/Object_Prop_Type/Array_Prop_Type分别做联合扩展并保留原有 meta。四、PHP 渲染 Transformerid →var(--label)的前端解析当组件在前端渲染、样式需要把变量 id解析成实际 CSS 值时由 Transformer 负责。注册入口是add_action( elementor/atomic-widgets/styles/transformers/register, function ( $registry ) { $registry-register( global-shadow-variable, new \My\Shadow_Variable_Transformer() ); } );关键限制务必注意仓库的 style-transformers.php 只为color 和 font两种类型注册了Global_Variable_Transformer$transformers_registry-register( Color_Variable_Prop_Type::get_key(), $transformer ); $transformers_registry-register( Font_Variable_Prop_Type::get_key(), $transformer );也就是说size token 没有对应的 PHP transformer——尺寸变量的解析发生在编辑器 JS 侧。这是刻意的设计取舍而非遗漏。Global_Variable_Transformer的解析规则见 global-variable-transformer.php按 id 查找变量Variables::by_id( $value )找不到返回null若目标 CSS 属性是 grid-track 属性Grid_Track_Renderer::is_grid_track_property()会把变量值当作 repeat 次数输出format_repeat( $count )若变量已被软删除deleted标志输出var(--{id})占位正常情况输出var(--{label})——因此变量 label 直接决定 CSS 自定义属性名label 为空时返回null。编辑器画布侧则使用StyleVariablesRenderer把变量集合渲染为:root { --label: value }形式注入。内置 size 类型在 JS 中走EmptyTransformer见下文而非默认的variableTransformer——这解释了为何 size 变量在前端需要特殊处理。如果你的新类型需要在前端 PHP 渲染时解析为var(...)就必须自己实现一个Transformer_Base子类并在这里注册如果只用于编辑器内或 REST/MCP 场景可以跳过本层。五、JS 层在 editor v2 包的init()中调用registerVariableType这是让新类型出现在编辑器 UI 的必要步骤。内置类型的 JS 注册集中在 register-variable-types.tsx 的registerVariableTypes()中——扩展方严禁编辑该核心文件必须在自己独立的 editor v2 包npm package的init()函数里调用registerVariableTypeimport { registerVariableType, variableTransformer } from elementor/editor-variables; import { stringPropTypeUtil } from elementor/editor-props; import { BrushIcon } from elementor/icons; import { shadowVariablePropTypeUtil } from ./prop-types/shadow-variable-prop-type; export function init() { registerVariableType( { key: shadowVariablePropTypeUtil.key, icon: BrushIcon, propTypeUtil: shadowVariablePropTypeUtil, fallbackPropTypeUtil: stringPropTypeUtil, variableType: shadow, defaultValue: 0 2px 4px rgba(0,0,0,0.1), styleTransformer: variableTransformer, } ); }其中必须提供的字段是key、icon、propTypeUtil、fallbackPropTypeUtil、variableType完整字段与valueFieldprop 契约参见 types.md下文第六节展开。为什么 JS 注册必不可少registerVariableType内部见 create-variable-type-registry.ts不仅把类型写入variableTypes映射还会同时调用registerTransformer( propTypeUtil.key, styleTransformer ); registerInheritanceTransformer( propTypeUtil.key );即把类型 key 注册进编辑器的styleTransformersRegistrystyleTransformer缺省时默认用variableTransformer与stylesInheritanceTransformersRegistry继承 transformer。跳过 JS 注册的 PHP-only 类型虽然可以通过 REST / MCP / CSS 正常工作但永远不会出现在 Add Variable 下拉菜单中——因为下拉列表由getVariableTypes()/hasVariableType()后者要求isActive true见 variable-type-registry.ts驱动而这些注册表只存在于编辑器 JS 运行时。无构建管线纯 WP 代码片段方案如果无法创建 npm 包/构建产物可以跳过构建管线直接在主题functions.php或代码片段插件里通过window.elementorV2.{camelCasePackage}全局对象对延迟加载的脚本执行注册——即把elementor/editor-variables暴露的registerVariableType从window.elementorV2.editorVariables上取出并调用。具体机制参见 extending-editor.mdEditor V2 的init()契约是window.elementorV2.{packageName}?.init?.()同步注册、不负责渲染。六、registerVariableType完整字段契约registerVariableType接受的选项VariableTypeOptions定义于 create-variable-type-registry.ts如下表。注意只有icon、propTypeUtil、fallbackPropTypeUtil、variableType是结构上必需的key缺省时取propTypeUtil.keyisActive缺省为true。字段类型作用keystring注册表 key /$$type缺省为propTypeUtil.keyiconicon 组件类型在变量选择器中的图标startIcon({ value }) JSX可选的前置指示图标如颜色色块valueField(props: ValueFieldProps) JSX值编辑组件variableTypestring逻辑分类color、font、size…defaultValuestring新建变量的初始值propTypeUtilPropTypeUtil绑定/解析存储的 PropValuefallbackPropTypeUtilPropTypeUtil变量无法解析时使用的回退类型工具styleTransformertransformer样式渲染转换器缺省为variableTransformervalueTransformer(value, type?) PropValue把原始输入规范化为 PropValueselectionFilter(variables, propType?) variables过滤可选变量列表isCompatible(propType, variable) boolean判断变量是否与某 prop 兼容缺省为联合成员检查emptyStateJSX无变量存在时的占位 UI常用于 Pro 升级 CTAisActiveboolean为false时从活跃列表 /hasVariableType中隐藏menuActionsFactory(context) actions[]变量管理器中的行操作valueField组件收到的ValueFieldProps为value、onChange、onValidationChange?、onPropTypeKeyChange?、propTypeKey?、propType?、error?、onKeyDown?。内置 color 类型的注册见 register-variable-types.tsx展示了上述字段的实际用法它为 color 类型提供了valueField: ColorField、startIcon色块指示器以及一个menuActionsFactory——用于在变量管理器中动态生成Sync to Global Colors / Stop syncing to Global Colors菜单项。七、REST 与 MCP类型注册是前置校验而非定义来源REST 端点命名空间elementor/v1基路径variables和 MCP 能力elementor/manage-global-variable只验证类型是否已注册不定义新类型。因此新类型必须先完成第二节的 PHP 注册才能被这些外部接口使用。REST 层的校验逻辑见 rest-api.php直接以注册表为准public function is_valid_variable_type( $type ) { $allowed_types array_keys( Variables_Module::instance()-get_variable_types_registry()-all() ); return in_array( $type, $allowed_types, true ); }端点概览来自 variables/api.md路由方法权限用途/variables/listGETedit_posts列出全部变量 watermark/variables/createPOSTmanage_options创建type、label、value/variables/updatePUT/PATCHmanage_options更新id、label、value可选order、type/variables/deletePOSTmanage_options软删除id/variables/restorePOSTmanage_options恢复id可选覆盖字段/variables/batchPOSTmanage_options批量操作watermark、operations[]字段校验上限同样定义在 rest-api.phpid ≤ 64 字符、label ≤ 50 字符且不允许空格、value ≤ 512 字符create/batch的type必须是Variable_Types_Registry::all()中的 key。批量操作支持create、update、delete、restore、reorder五种动作并依赖watermark做乐观并发控制。所有写操作成功后都会调用clear_cache()Plugin::$instance-files_manager-clear_cache()刷新文件缓存。存储形态上变量保存在激活 Kit 的 meta_elementor_global_variables中形如{ data: { e-gv-abc123: { type: global-color-variable, label: wc26-gold, value: #C6A15B, order: 1 } }, watermark: 5, version: 2 }MCP 侧对应两个入口资源elementor://global-variables返回{ variables, total, watermark }与能力elementor/manage-global-variable批量 1–50 个操作。在组合 CSS 时使用label在 update/delete 时使用id。Kit 导出/导入则通过global-variables.json文件与variablesOverrideAll冲突解决策略完成相关实现见 hooks.php 中挂载的Template_Library_Variables系列过滤器。八、内置类型与 Pro 门控理解 size 类型的特殊地位size 类型global-size-variable/global-custom-size-variable在仓库中的实现颇具代表性值得作为理解变量类型扩展边界的样例PHP 侧无 size transformer如第四节所述Style_Transformers只注册 color/fontsize 变量由编辑器 JS 解析。JS 侧以促销态注册免费版核心 JS 包确实注册了两个 size key但传入了isActive: false、styleTransformer: EmptyTransformer、selectionFilter: () []并提供一个emptyStateCTAgo.elementor.com/go-pro-panel-size-variable/见 register-variable-types.tsx 中的sizePromotions对象——于是选择器显示的是升级引导而非可编辑字段。Pro 的 editor variables 包会把相同 key 以激活状态重新注册UI 才能真正编辑 size 变量。Schema 侧有版本门控Size_Style_Schema对 grid-track 属性要求 Pro ≥ 4.2 才并入 size 变量联合同时跳过 angle/time 单位属性。这意味着如果你扩展的类型本身是 Pro 功能可以照搬这套免费包注册促销态 Pro 包激活的双包模式而扩展普通类型时直接传isActive: true缺省即可。九、实践清单与常见陷阱完成一次变量类型扩展按顺序核对以下清单✅ 确认e_atomic_elements实验已激活变量模块加载前提见 module.php✅ 在init之前挂elementor/variables/register注册自定义 PropType 与 key✅ 通过elementor/atomic-widgets/styles/schema把新$$type并入目标样式属性的联合类型镜像 style-schema.php 的递归更新逻辑✅ 若需要前端 PHP 渲染通过elementor/atomic-widgets/styles/transformers/register注册自己的 Transformer若仅编辑器场景可跳过✅ 在独立 editor v2 包的init()中调用registerVariableType绝不改核心 register-variable-types.tsx至少提供key、icon、propTypeUtil、fallbackPropTypeUtil、variableType✅ 通过elementor/v1/variables/batch或 MCPelementor/manage-global-variable用新$$type创建变量验证 REST/MCP 的is_valid_variable_type校验通过。最常见的三个坑只做 PHP 注册、漏掉 JS 注册——类型能通过 REST/MCP 创建、能被 CSS 引用但编辑器 Add Variable 下拉里永远看不到漏掉 Style Schema 联合——即使类型已注册对应样式属性也不会接受该$$type校验直接失败在init之后才挂监听器——elementor/variables/register由Module::init_variable_types_registry()在init钩子内触发挂晚了注册表已经定型register()只是写入数组不会重复触发 do_action。十、延伸阅读变量类型详解与内置类型对照Transformable_Prop_Type、注册表生命周期、Pro 语义变量 REST / MCP / Kit 导入导出 API端点、存储形态、watermark 并发控制Editor V2 扩展机制editor v2 包注册、window.elementorV2全局、init()契约extend-variables 技能文档与本文对应的官方技能描述【免费下载链接】elementorThe most advanced frontend drag drop page builder. Create high-end, pixel perfect websites at record speeds. Any theme, any page, any design.项目地址: https://gitcode.com/GitHub_Trending/el/elementor创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考