WordPress 6.3 引入命令面板,同时提供了让开发者扩展命令的 API。在 Mac 上按 Cmd + K、在 Windows 上按 Ctrl + K,便可打开面板,输入并搜索命令。
图 1:站点编辑器上方打开命令面板,展示可以搜索、执行的命令。原教学图见官方图片。
原教程发表于2023年11月20日。以下界面与 API 范围描述针对 WordPress 6.4:当时命令面板仅在文章编辑器和站点编辑器中提供,作者预期未来可能扩展到整个后台。这不是对当前版本覆盖范围的保证。6.4 对界面作了改进,也增加了内置命令,例如:
- 新增文章或页面;
- 编辑已有文章或页面;
- 打开样板库;
- 切换用户偏好。
这些是通过键盘浏览 WordPress 界面的基础命令。命令面板 API 还允许开发者用少量 JavaScript 添加自定义命令。可注册的命令分为静态命令和动态命令。本文讲解静态命令;动态命令及命令加载器见命令面板 API 开发说明。
前置知识
虽然本文介绍 API 的基础用法,但仍属于进阶教程。开始前,应熟悉 @wordpress/scripts以及通过它的 start、build 命令处理 JavaScript。
自定义命令通常通过插件添加,也可以通过主题添加。在主题中配置 @wordpress/scripts的方法,见Beyond block styles, part 1。
阅读 @wordpress/commands 文档有助于理解后面的代码,但不是开始本教程的必要条件。
注册静态命令
注册静态命令有两种方式:
wp.data.dispatch( wp.commands.store ).registerCommand()action;wp.commands.useCommand()React hook。
两者接受相同参数,主要区别是 useCommand() 必须在 React 组件内部使用;组件外应使用 registerCommand()。它们都接受一个对象,可设置以下属性:
name:命令唯一的命名空间与 slug。label:在命令面板中显示的标签。searchLabel:可选,用于匹配用户搜索内容;面板实际显示的仍是label。context:可选,让命令出现在特定界面的默认命令列表。原教程列出site-editor(站点编辑器主界面)和site-editor-edit(在站点编辑器中编辑模板)。icon:显示在标签旁的 SVG 图标,以 React 组件提供。callback:用户选择命令时执行的回调。
下面是 registerCommand() 的调用形式:
wp.data.dispatch( wp.commands.store ).registerCommand( {
name: 'your-namespace/your-command-slug',
label: 'Command label',
searchLabel: 'Command search label',
icon: icon,
context: 'site-editor',
callback: ( { close } ) => {
close();
}
} );
熟悉 WordPress JavaScript 的开发者通常能直接理解这些属性。主要需要决定的是 callback 执行什么操作,这就是命令本身的行为。
构建一个示例命令插件
接下来按原教程构建一个添加自定义命令的插件。
设置插件
在 WordPress 安装目录的 wp-content/plugins 中新建插件,文件结构如下:
build/:保存 WordPress 工具编译出的文件。src/index.js:JavaScript 源文件。index.php:插件入口。package.json:包与脚本配置。
在 package.json 中至少定义 start 和 build:
{
"scripts": {
"start": "wp-scripts start",
"build": "wp-scripts build"
}
}
通过 CLI 安装 @wordpress/scripts:
npm install @wordpress/scripts --saveDev
还需要安装 @wordpress/icons:
npm install @wordpress/icons
接着在 index.php 中加入插件文件头,例如:
<?php
/**
* Plugin Name: Dev Blog: Command Palette API
* Plugin URI: https://developer.wordpress.org/news/
* Description: Showcases examples of adding static commands via the Command Palette API.
* Version: 1.0.0
* Requires at least: 6.4
* Requires PHP: 7.4
* Author: WordPress Developer Blog
* Author URI: https://developer.wordpress.org/news/
* Text Domain: dev-blog
*/
启用示例插件后,运行开发构建命令:
npm run start
加载编辑器脚本
这里没有注册自定义区块,WordPress 不会自动加载 JavaScript,因此需要主动加载 build/index.js。原文说明段写的是 enqueue_block_editor_scripts,但紧随其后的代码实际使用 enqueue_block_editor_assets。下面保留原始代码,并明确这一原文差异,避免把不同名称混为同一个 hook。
在插件的 index.php 中加入:
add_action( 'enqueue_block_editor_assets', 'devblog_command_api_editor_assets' );
function devblog_command_api_editor_assets() {
$asset_file = trailingslashit( __DIR__ ) . 'build/index.asset.php';
if ( file_exists( $asset_file ) ) {
$asset = include $asset_file;
wp_enqueue_script(
'devblog-command-api',
trailingslashit( plugin_dir_url( __FILE__ ) ) . 'build/index.js',
$asset['dependencies'],
$asset['version'],
true
);
}
}
导入依赖
打开 src/index.js,准备导入注册命令所需的依赖:@wordpress/commands、@wordpress/data、@wordpress/i18n 和 @wordpress/icons。
在文件顶部添加:
import { store as commandsStore } from '@wordpress/commands';
import { dispatch } from '@wordpress/data';
import { __ } from '@wordpress/i18n';
import { settings, comment, button } from '@wordpress/icons';
现在可以尝试以下命令示例。
示例 1:跳转到后台页面
先添加一个跳转到 WordPress 后台其他页面的命令。
图 2:站点编辑器的命令面板中搜索 “gutenberg”,结果列表包含 Gutenberg Experiments。原教学图见官方图片。
原作者选择的是 Gutenberg Experiments 设置界面,需要启用 Gutenberg 插件。也可以将代码中的 URL 改成其他目标页面。
跳转通过设置 JavaScript document.location 对象的 href 属性完成。在 src/index.js 中添加:
dispatch( commandsStore ).registerCommand( {
name: 'dev-blog/gutenberg-experiments',
label: __( 'Gutenberg Experiments', 'dev-blog' ),
icon: settings,
context: 'site-editor',
callback: ( { close } ) => {
document.location.href = 'admin.php?page=gutenberg-experiments';
close();
}
} );
测试时,打开命令面板并输入 “Gutenberg Experiments”。按原教程预期,命令会出现在结果中,选择后应跳转到相应后台界面。
示例 2:切换编辑器面板
这个命令用于启用或禁用文章编辑器中的“讨论”面板。
图 3:文章编辑器的命令面板中搜索切换讨论面板的命令。原教学图见官方图片。
只要知道面板名称,也可以切换其他面板。“讨论”面板的名称是 discussion-panel。将名称传给 core/edit-post 的 toggleEditorPanelEnabled() action 即可。
在 src/index.js 中添加:
dispatch( commandsStore ).registerCommand( {
name: 'dev-blog/discussion-panel',
label: __( 'Toggle discussion panel', 'dev-blog' ),
icon: comment,
callback: ( { close } ) => {
dispatch( 'core/edit-post' ).toggleEditorPanelEnabled(
'discussion-panel'
);
close();
}
} );
并非每个编辑器都有相同面板。例如,讨论面板存在于文章编辑器,但不在站点编辑器中显示。因此在站点编辑器执行这个命令,看不到相应结果。
原作者没有认定这种体验最佳。另一种选择是仅在文章编辑界面注册命令:检查 wp.editPost 是否已定义,然后将上述代码包进条件判断:
if ( undefined !== wp.editPost ) {
dispatch( commandsStore ).registerCommand( {
name: 'dev-blog/discussion-panel',
label: __( 'Toggle discussion panel', 'dev-blog' ),
icon: comment,
callback: ( { close } ) => {
dispatch( 'core/edit-post' ).toggleEditorPanelEnabled(
'discussion-panel'
);
close();
}
} );
}
原作者对条件式命令是否改善体验也持开放态度,并邀请读者讨论如何处理。
示例 3:切换用户偏好
再添加一个命令,切换编辑器界面按钮显示图标还是文字标签。
图 4:站点编辑器正在编辑单篇文章模板,命令面板中搜索切换按钮标签的命令。原教学图见官方图片。
这个例子也依赖编辑器上下文。用户偏好分别按站点编辑器和文章编辑器保存。
检查 wp.editPost 可判断是否在文章编辑器;站点编辑器对应的对象是 wp.editSite。切换偏好使用 core/preferences 数据模块的 toggle() action,需要提供编辑器名称(core/edit-site 或 core/edit-post)和偏好名称。这里要切换的是 showIconLabels。
将以下代码加入 src/index.js:
dispatch( commandsStore ).registerCommand( {
name: 'dev-blog/toggle-button-labels',
label: __( 'Toggle button labels', 'dev-blog' ),
icon: button,
context: 'site-editor-edit',
callback: ( { close } ) => {
// Toggles preference for site editor.
if ( undefined !== wp.editSite ) {
dispatch( 'core/preferences' ).toggle(
'core/edit-site',
'showIconLabels'
);
}
// Toggles preference for post editor.
else if ( undefined !== wp.editPost ) {
dispatch( 'core/preferences' ).toggle(
'core/edit-post',
'showIconLabels'
);
}
close();
}
} );
是否使用条件判断由开发者决定。也可以不论当前在哪个编辑器,都同时切换两者的偏好。这样仍需要两次 dispatch( 'core/preferences' ).toggle() 调用,只是移除包在外面的条件判断。
示例 4:在组件内部注册命令
前面的命令从组件外注册,但插件中经常需要在组件内部工作。这里进一步改进示例 2:把命令放进组件,根据面板当前状态显示不同标签,并在状态改变时于左下角显示 snackbar 通知。
图 5:文章编辑器中显示讨论面板的条件式命令;状态改变时出现通知。原教学图见官方图片。
先更新导入:从 @wordpress/commands 导入 useCommand,从 @wordpress/data 导入 useDispatch 与 useSelect,并导入 registerPlugin。**原文项目列表将后者误写成 @wordpress/buttons,实际代码来自 @wordpress/plugins。**以下仍保留原始代码。
将 index.js 的导入改成:
import { store, useCommand } from '@wordpress/commands';
import { dispatch, useDispatch, useSelect } from '@wordpress/data';
import { __ } from '@wordpress/i18n';
import { settings, search, comment, button } from '@wordpress/icons';
import { registerPlugin } from '@wordpress/plugins';
注意:这一示例把 commands store 导入为 store,而前面示例用的是 commandsStore 别名。若把多个示例合并为同一文件,需要自行统一引用;原教程没有提供合并后的完整文件。
接着添加:
if ( undefined !== wp.editPost ) {
registerPlugin( 'dev-blog-command-palette', {
render: () => {
// Determine if the discussion panel is enabled.
const discussionPanelEnabled = useSelect( ( select ) => {
return select( 'core/edit-post' ).isEditorPanelEnabled(
'discussion-panel'
);
}, [] );
// Get functions for toggling panels and creating snackbars.
const { toggleEditorPanelEnabled } = useDispatch( 'core/edit-post' );
const { createInfoNotice } = useDispatch( 'core/notices' );
// Register command to toggle discussion panel.
useCommand( {
name: 'dev-blog/discussion-show-hide',
label: discussionPanelEnabled
? __( 'Hide discussion panel', 'dev-blog' )
: __( 'Show discussion panel', 'dev-blog' ),
icon: comment,
callback: ( { close } ) => {
// Toggle the discussion panel.
toggleEditorPanelEnabled( 'discussion-panel' );
// Add a snackbar notice.
createInfoNotice(
discussionPanelEnabled
? __( 'Discussion panel hidden.', 'dev-blog' )
: __( 'Discussion panel displayed.', 'dev-blog' ),
{
id: 'dev-blog/toggle-discussion/notice',
type: 'snackbar'
}
);
close();
}
} );
}
} );
}
这些函数与 hook 分工如下:
registerPlugin():提供渲染组件的包装。useCommand():注册显示或隐藏讨论面板的命令。useSelect():从core/edit-poststore 读取数据,其中isEditorPanelEnabled()判断讨论面板是否启用。useDispatch():获取core/edit-post和core/notices的 action,其中toggleEditorPanelEnabled()切换面板,createInfoNotice()创建 snackbar 通知。
这些例子提供了开始使用命令面板 API 所需的基础。原作者也邀请开发者分享计划构建的功能。
来源与许可
原文:Getting started with the Command Palette API,作者 Justin Tadlock,发表于2023年11月20日。原文感谢 @dansoschin、@bph、@juanmaguitar 和 @richtabor 提供反馈与审阅。中文稿于2026-10-03按原文正文整理,并标明历史版本范围和原文不一致处。
按照 WordPress Documentation Licensing,覆盖 developer.wordpress.org/ 的文档文字和图片按 CC0提供,示例代码按 GNU GPL v2 或更新版本提供。代码未修改;完整 GPL v2 许可见官方许可全文。正式分发代码时应同时提供该许可文本。











暂无评论内容