news 2026/9/17 1:36:18

使用 PluginMoreMenuItem 为 WordPress 块编辑器注入“更多工具与选项“菜单项

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
使用 PluginMoreMenuItem 为 WordPress 块编辑器注入“更多工具与选项“菜单项

使用 PluginMoreMenuItem 为 WordPress 块编辑器注入"更多工具与选项"菜单项

【免费下载链接】gutenbergThe Block Editor project for WordPress and beyond. Plugin is available from the official repository.项目地址: https://gitcode.com/GitHub_Trending/gu/gutenberg

PluginMoreMenuItem是 Gutenberg 编辑器包(@wordpress/editor)提供的 SlotFill 组件,允许插件在块编辑器右上角"更多工具与选项"(More Tools & Options)下拉菜单中注入自定义菜单项。本文将以 docs/reference-guides/slotfills/plugin-more-menu-item.md 为骨架,结合仓库源码(packages/editor/src/components/plugin-more-menu-item/index.jsx、packages/editor/src/components/more-menu/index.jsx 等)深入讲解其用法、Props、底层原理、条件渲染与迁移注意事项,读完即可在你的插件中实现一个功能完整的菜单项。

PluginMoreMenuItem 是什么

PluginMoreMenuItem是一个 SlotFill 扩展点,其作用正如官方文档所述:

This slot will add a new item to the More Tools & Options section.

即向块编辑器界面右上角的"选项(Options)"下拉菜单(即通常所说的 More Menu)中新增一个菜单条目。该条目可以表现为按钮(执行回调)或链接(跳转 URL),具体取决于传入的 Props。

SlotFill 是 Gutenberg 暴露给开发者的扩展机制,允许把内容注入到编辑器预先定义好的位置。按照 SlotFills 参考文档 的说明,使用任何 SlotFill 都需要四步:

  1. @wordpress/plugins导入registerPlugin
  2. @wordpress/editor导入所需的 SlotFill 组件(这里是PluginMoreMenuItem);
  3. 定义一个渲染自定义内容的组件,把要注入的内容包裹在 SlotFill 组件内部;
  4. 调用registerPlugin注册插件。

PluginMoreMenuItem与同类的PluginSidebarMoreMenuItemPluginBlockSettingsMenuItemPluginDocumentSettingPanel等组件共同组成了编辑器的官方扩展体系,完整的 SlotFill 清单可参考 SlotFills Reference。

快速上手:注入一个按钮型菜单项

官方文档给出了最简示例。下面的代码注册一个插件,在 More Menu 中新增一个带图标的菜单项,点击时弹出提示框:

import { registerPlugin } from '@wordpress/plugins'; import { PluginMoreMenuItem } from '@wordpress/editor'; import { image } from '@wordpress/icons'; const MyButtonMoreMenuItemTest = () => ( <PluginMoreMenuItem icon={ image } onClick={ () => { alert( 'Button Clicked' ); } } > More Menu Item </PluginMoreMenuItem> ); registerPlugin( 'more-menu-item-test', { render: MyButtonMoreMenuItemTest } );

要点拆解:

  • registerPlugin( 'more-menu-item-test', { render: ... } ):插件名必须全局唯一,render传入要渲染的 React 组件;
  • <PluginMoreMenuItem>children 即菜单项的显示文本("More Menu Item");
  • icon传入@wordpress/icons中的 SVG 图标;
  • onClick是点击菜单项时执行的回调。

菜单项出现的位置在编辑器右上角的竖向省略号(Options)下拉菜单中。在该菜单展开时,插件注入的条目会出现在"面板(Panels)"分组中,与编辑器内置的视图切换(Visual editor / Code editor)等条目同属一个大菜单。

核心 API 与 Props 详解

根据组件源码 JSDoc(packages/editor/src/components/plugin-more-menu-item/index.jsx#L9-L14),PluginMoreMenuItem支持以下 Props:

Prop类型默认值说明
childrenReact.ReactNode菜单项的显示内容,通常为标签文本
hrefstring提供时菜单项渲染为<a>链接而非按钮,对应锚点的href属性
iconDashicon slug 字符串或 SVG WP 元素继承自插件渲染在菜单项标签左侧的图标
onClickFunctionnoop用户点击菜单项时执行的回调函数
其他 Props...*透传给底层菜单项组件;as已被废弃并忽略

几个值得注意的行为:

  • icon默认继承插件图标。源码中icon={ itemProps.icon || context.icon }context来自usePluginContext()(packages/editor/src/components/plugin-more-menu-item/index.jsx#L62-L81)。因此如果你在registerPlugin时设置了插件的icon,菜单项会自动使用它,无需重复传入。
  • href决定渲染形态。传入href时菜单项变成链接(源码中由more-menu-group.tsxtoMenuItems根据fill.props.href !== undefined选择渲染Menu.LinkItem还是Menu.Item,见 more-menu-group.tsx#L64-L72)。
  • as已废弃。源码检测到as时调用deprecated()并忽略该属性(自版本 7.2 起),因为菜单项由菜单自身的机制渲染,不需要外部指定组件。

使用 ES5 语法的写法

源码 JSDoc 中还保留了基于wp.*全局对象的 ES5 示例,适用于未使用构建工具的环境:

var __ = wp.i18n.__; var PluginMoreMenuItem = wp.editor.PluginMoreMenuItem; var moreIcon = wp.element.createElement( 'svg' ); // ...svg element. function onButtonClick() { alert( 'Button clicked.' ); } function MyButtonMoreMenuItem() { return wp.element.createElement( PluginMoreMenuItem, { icon: moreIcon, onClick: onButtonClick, }, __( 'My button title' ) ); }

现代开发建议直接使用import语法(ESNext),因为wp.editor.PluginMoreMenuItem需要你的插件在编辑器环境(@wordpress/editor已加载)中运行。

源码原理:从 PluginMoreMenuItem 到菜单渲染

要理解这个 SlotFill 的完整链路,需要沿着源码走一遍。

1. 组件本身只是 ActionItem 的封装

PluginMoreMenuItem的真实实现非常轻量(packages/editor/src/components/plugin-more-menu-item/index.jsx#L62-L81):

export default function PluginMoreMenuItem( props ) { const context = usePluginContext(); const { as, ...itemProps } = props; if ( as ) { deprecated( 'The `as` prop of wp.editor.PluginMoreMenuItem', { since: '7.2', hint: 'The menu renders the item itself. The prop is ignored.', } ); } return ( <ActionItem name="core/plugin-more-menu" icon={ itemProps.icon || context.icon } { ...itemProps } /> ); }

它把一切交给@wordpress/interface包的ActionItem,并指定了 Slot 名称为core/plugin-more-menu

2. ActionItem 通过 Slot/Fill 建立连接

ActionItemFill(填充方,即你的插件)与ActionItem.Slot(槽位方,即编辑器菜单)两部分组成(packages/interface/src/components/action-item/index.tsx):

  • ActionItem渲染<Fill name={ name }>,把自身作为填充内容注入槽位;
  • ActionItem.Slot渲染<Slot name={ name }>,收集所有同名 Fill,通过children函数(render prop)交给菜单渲染。

ActionItem有一个关键交互设计:槽位会把"用于渲染菜单项的组件"(as,默认MenuItem)和"关闭菜单的 onClick"通过fillProps传给每个 Fill。Fill 端的onClick不会替换槽位的 handler,而是两者串联执行(action-item/index.tsx#L33-L60):

const Component = as ?? slotAs; const handlers = [ onClick, slotOnClick ].filter( Boolean ); // ...合并调用所有 handlers

这意味着你写的onClick执行后,菜单还会自行关闭,无需手动处理。

3. 编辑器 More Menu 中的槽位

真正的"插槽"位于编辑器头部菜单组件中(packages/editor/src/components/more-menu/index.jsx#L114-L123):

<ActionItem.Slot name="core/plugin-more-menu" fillProps={ { as: MoreMenuItem } } > { ( items ) => ( <MoreMenuGroup label={ __( 'Panels' ) }> { items } </MoreMenuGroup> ) } </ActionItem.Slot>

可以看到:

  • 槽位名称core/plugin-more-menuPluginMoreMenuItem内部使用的名称完全一致;
  • fillProps.as被设为编辑器的MoreMenuItem,因此你的菜单项最终由编辑器自己的菜单项组件渲染,保证风格与无障碍行为一致;
  • 所有插件注入的条目被统一收进 label 为Panels(面板)的分组,组内由 MoreMenuGroup 负责把每个 Fill 转换为Menu.Item(按钮)或Menu.LinkItem(链接)。

4. 分组与键盘导航

MoreMenuGrouptoMenuItems函数(more-menu-group.tsx#L49-L73)负责把"自带渲染内容的 Fill"包装成真正参与菜单键盘导航的菜单项,并利用renderprop 保留 Fill 自身的渲染输出。也就是说,即使你的组件没有使用编辑器提供的MoreMenuItem,它也会被正确包装进菜单的无障碍导航树中。

进阶实践:链接菜单项与条件渲染

渲染为链接

需要跳转时传入href,菜单项即变为链接:

import { registerPlugin } from '@wordpress/plugins'; import { PluginMoreMenuItem } from '@wordpress/editor'; import { external } from '@wordpress/icons'; const MyLinkMoreMenuItem = () => ( <PluginMoreMenuItem href="https://example.com/docs" icon={ external } target="_blank" > View documentation </PluginMoreMenuItem> ); registerPlugin( 'more-menu-item-link', { render: MyLinkMoreMenuItem } );

href之外的其他 Props(如target)会透传给底层菜单项组件。菜单对链接型条目会渲染为Menu.LinkItem,支持target="_blank"新窗口打开。

控制注入时机与范围

根据 SlotFills 参考文档 的说明,绝大多数 SlotFill(包括PluginMoreMenuItem)在文章编辑器(Post Editor)与站点编辑器(Site Editor)中都会渲染,因此通常需要自行控制显示范围。常用手法包括:

  • 限制在文章编辑器:通过editorStore.getCurrentPostType()coreStore.getPostType()判断当前文章类型的viewable属性是否为true
  • 限制在特定文章类型:维护一个允许列表,如[ 'page' ],仅在该列表内渲染;
  • 限制在站点编辑器:与上面逻辑相反,非 viewable 的内部文章类型(如wp_templatewp_template_partwp_block)即站点编辑器场景。

示例(仅对 page 文章类型显示菜单项):

import { registerPlugin } from '@wordpress/plugins'; import { PluginMoreMenuItem, store as editorStore } from '@wordpress/editor'; import { store as coreStore } from '@wordpress/core-data'; import { useSelect } from '@wordpress/data'; import { settings } from '@wordpress/icons'; const PageOnlyMoreMenuItem = () => { const isPage = useSelect( ( select ) => { const postType = select( editorStore ).getCurrentPostType(); return postType === 'page'; }, [] ); if ( ! isPage ) { return null; } return ( <PluginMoreMenuItem icon={ settings }> Page-only action </PluginMoreMenuItem> ); }; registerPlugin( 'page-only-more-menu-item', { render: PageOnlyMoreMenuItem } );

结合其他 SlotFill 使用

PluginMoreMenuItem常与PluginSidebar配合:通过PluginSidebarMoreMenuItem打开侧边栏。若你的侧边栏开关已经存在于"更多工具与选项"菜单中,注意不要让菜单项重复;PluginSidebarMoreMenuItem内部同样基于core/plugin-more-menu槽位机制工作,属于同一体系(相关组件清单见 packages/editor/src/components/index.js#L28)。

兼容性与迁移说明

历史上PluginMoreMenuItem同时从@wordpress/edit-post暴露(wp.editPost.PluginMoreMenuItem)。在 packages/edit-post/src/deprecated.jsx 中可以确认,该别名自6.6起已废弃:

const deprecateSlot = ( name ) => { deprecated( `wp.editPost.${ name }`, { since: '6.6', alternative: `wp.editor.${ name }`, } ); };

并且wp.editPost版本的PluginMoreMenuItem在站点编辑器(site-editor.php)中会直接返回null(deprecated.jsx#L17-L19、deprecated.jsx#L54-L60)。因此:

  • 新代码一律从@wordpress/editor导入PluginMoreMenuItem
  • 旧代码应迁移wp.editPost.PluginMoreMenuItemwp.editor.PluginMoreMenuItem
  • @wordpress/edit-site暴露的同名别名同样是迁移桩(见 packages/edit-site/src/deprecated.jsx#L24-L29),同样应改用@wordpress/editor

无障碍与测试保障

菜单项最终由@wordpress/uiMenu体系渲染,自带完整的键盘导航、ARIA 角色与焦点管理。仓库中的单元测试(packages/editor/src/components/more-menu/test/more-menu-item.jsdom.test.tsx)覆盖了以下关键行为,可作为你实现菜单项时的参考基准:

  • 复选框/单选角色保留role="menuitemcheckbox"menuitemradioaria-checked状态会被正确保留,isSelected也能驱动选中态;
  • 链接渲染href空字符串也渲染为链接;target="_blank"生效;disabled链接变为不可交互项并带aria-disabled="true"
  • 快捷键显示:支持字符串或{ display, ariaLabel }对象形式的shortcut,并提供可访问的快捷键描述;
  • Dashicon:以 slug 传入的图标(如"editor-kitchensink")会渲染对应的.dashicons类名。

小结

PluginMoreMenuItem是一个"薄封装 + 强生态"的扩展点:组件本身只有约 20 行代码,但经由ActionItem(packages/interface/src/components/action-item/index.tsx)与core/plugin-more-menu槽位,被无缝接入编辑器右上角"更多工具与选项"菜单的 Panels 分组,并获得图标继承、链接/按钮双形态、菜单关闭联动与无障碍键盘导航等能力。

实际开发时只需记住:从@wordpress/editor导入、用registerPlugin注册、用icon/href/onClick/children 控制形态,并按需用editorStore/coreStore做条件渲染。若想了解更多注入点,可继续阅读 SlotFills Reference 中列出的其他 SlotFill 文档,或查看 @wordpress/plugins 包说明 了解插件注册 API 的完整用法。

【免费下载链接】gutenbergThe Block Editor project for WordPress and beyond. Plugin is available from the official repository.项目地址: https://gitcode.com/GitHub_Trending/gu/gutenberg

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/17 1:35:54

ArcGIS等高线转DEM全流程详解:地形转栅格与插值方法实战

等高线转DEM&#xff0c;这活儿在ArcGIS里算是最常见的栅格处理需求之一&#xff0c;但真正动手做过的朋友都知道&#xff0c;坑远比想象的多。坐标系没统一、等高线有断头、属性字段是字符串、栅格分辨率拍脑袋乱填……任何一个环节出问题&#xff0c;出来的DEM要么有台阶感&a…

作者头像 李华
网站建设 2026/9/17 1:35:16

云原生MySQL兼容数据库内核差异深度解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/17 1:34:05

RADIOML 2018.01A实战指南:从数据加载到调制识别评估

搞自动调制识别&#xff08;AMC&#xff09;的人&#xff0c;手边大概率绕不开RADIOML。RADIOML 2018.01A是DeepSig公开的无线信号调制识别数据集&#xff0c;也是目前AMC算法验证用得最频繁的标准benchmark之一。我做频谱监测和认知无线电相关项目时&#xff0c;第一次想把这个…

作者头像 李华
网站建设 2026/9/17 1:33:27

GD32F470 USB HOST与U盘IAP固件升级实战指南

简介&#xff1a;面向嵌入式开发者的GD32F470 USB Host实战资源&#xff0c;演示用C语言驱动USB主机读写U盘&#xff0c;并实现基于U盘的IAP固件升级&#xff0c;适合需要掌握GD32 USB OTG与Bootloader设计的工程师。压缩包共180个文件&#xff0c;以87个h头文件、74个c源文件和…

作者头像 李华
网站建设 2026/9/17 1:33:04

车载氛围灯PCBA开发解析:LED驱动、光学设计与量产可靠性

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/17 1:30:58

Excel自动备份方案:VBA实现数据安全与高效管理

1. 为什么你需要一个Excel自动备份方案作为一名长期与Excel打交道的财务分析师&#xff0c;我深知数据丢失的痛苦。去年第三季度财报截止日前夜&#xff0c;我连续工作了12小时完成的合并报表因为系统崩溃而丢失&#xff0c;那种绝望感至今记忆犹新。正是这次惨痛教训促使我开发…

作者头像 李华