如何构建古腾堡插件以增强区块编辑器功能

如何构建古腾堡插件以增强区块编辑器功能

多年来,我们从多个角度对古腾堡进行了探索。我们剖析了编辑器的功能,与其他页面构建工具进行了比较,构建了静态动态自定义区块,等等。

在最新版本的 WordPress 中,新功能和新工具通过丰富和增强区块编辑器的功能,让您可以更轻松地创建复杂的布局,而无需构建自定义区块。

由于引入了区块样板和开发者工具(如区块绑定 API),自定义区块的用例越来越少。现在,您可以创建复杂的区块结构,在内容中注入元数据值,并在不离开编辑器界面的情况下自动执行大部分工作流程。简而言之,WordPress让您可以像以前一样,只需点击几下就能创建复杂的网站。

在编辑器中添加自定义控件和工具可以让内容创建过程更加顺畅。例如,您可能需要在 “文章” 侧边栏中添加一个面板来增加功能,或者创建一个自定义侧边栏来管理多个元字段。

如何在不创建自定义区块的情况下创建区块编辑器插件

WordPress 提供了一个方便的命令行工具,允许您安装一个本地 Node.js 开发环境,其中包含创建自定义区块所需的所有文件和依赖项。只需在命令行工具中键入 npx @wordpress/create-block,等待几秒钟,就大功告成了。

不过,当你只需要添加一个侧边栏或一个简单的设置面板时,就没有必要为自定义区块搭建脚手架了。在这种情况下,您需要创建一个古腾堡插件。

WordPress 没有提供自动创建 Gutenberg 插件的工具,因此您需要手动创建。不过不用太担心。这个过程相对简单,我们将引导您完成。具体步骤如下:

1. 下载并安装本地开发环境

先做第一件事: 虽然您可以在远程环境中开发 Gutenberg 插件,但在本地安装一个开发 WordPress 网站可能更方便。您可以使用任何基于 PHP 和 MySQL 的环境。在众多替代方案中,我们推荐MAMP。它功能齐全、易于使用。

设置好开发网站后,您就可以创建 Gutenberg 区块编辑器插件了。

2. 下载并安装 Node.js 和 npm

nodejs.org 下载 Node.js 并安装到您的电脑上。这还将安装 Node 软件包管理器 npm。

安装完成后,启动命令行工具并运行 node -vnpm -v 。您将看到 Node.js 和 npm 的安装版本。

检查 node 和 npm 版本

检查 node 和 npm 版本

3. 创建插件文件夹

wp-content/plugins 下新建一个文件夹,并将其重命名为 my-sidebar-plugin 或类似名称。记住,这个名称应反映你的插件名称。

打开终端,导航到插件文件夹,然后使用以下命令初始化一个 npm 项目:

npm init -y

这将创建一个基本的 package.json 文件。

创建基本 package.json 文件

创建基本 package.json 文件

4. 安装依赖项

在命令行工具中键入以下命令:

npm install @wordpress/plugins @wordpress/scripts --save-dev
  • @wordpress/plugins安装WordPress 的 plugins 模块
  • @wordpress/scripts安装用于 WordPress 开发的可重用脚本集合。

一个新的 node_modules 文件夹应该已经添加到你的项目中。

现在,打开 package.json,更新 scripts 如下:

{
"name": "my-sidebar-plugin",
"version": "1.0.0",
"main": "index.js",
"scripts": {
"build": "wp-scripts build",
"start": "wp-scripts start"
},
"keywords": [],
"author": "",
"license": "ISC",
"description": "",
"devDependencies": {
"@wordpress/plugins": "^7.14.0",
"@wordpress/scripts": "^30.7.0"
}
}

现在可以检查插件文件夹了:

Visual Studio Code 中的插件项目

Visual Studio Code 中的插件项目

5. 创建插件文件

在插件目录下新建一个 .php 文件,文件名与文件夹相同。在我们的例子中,文件名是 my-sidebar-plugin.php

打开文件并粘贴以下代码,以便在服务器上注册插件:

<?php
/**
* Plugin Name: My Sidebar Plugin
*/
function my_sidebar_plugin_register_script() {
wp_enqueue_script(
'my_sidebar_plugin_script',
plugins_url( 'build/index.js', __FILE__ ),
array( 'wp-plugins', 'wp-edit-post' ),
filemtime( plugin_dir_path( __FILE__ ) . 'build/index.js' )
);
}
add_action( 'enqueue_block_editor_assets', 'my_sidebar_plugin_register_script' );

接下来,在插件目录下创建一个 src 文件夹。在其中创建一个新的 index.js 文件,代码如下:

import { registerPlugin } from '@wordpress/plugins';
import { PluginSidebar } from '@wordpress/edit-post';
const MyPluginSidebar = () => (
<PluginSidebar
name="my-sidebar-plugin"
title="My Sidebar Plugin"
>
<div>
Hello my friends!
</div>
</PluginSidebar>
);
registerPlugin( 'my-sidebar-plugin', {
render: MyPluginSidebar,
} );

6. 编译代码

现在就差编译了。返回命令行并运行以下命令:

npm run build

这会创建一个包含项目压缩文件的 build 文件夹。

VSC 中的插件项目文件夹

VSC 中的插件项目文件夹

完成后,导航到 WordPress 面板中的插件界面,激活插件。创建一个新的文章或页面,点击右上角的插件图标,显示自定义侧边栏。

文章编辑器中的自定义侧边栏

文章编辑器中的自定义侧边栏

7. 开发和构建

我们将 index.js 文件放在 src 文件夹中。在 WordPress 插件和主题开发中,使用 src 文件夹是一种常见的惯例,这样可以让其他开发人员更容易理解您的代码。

将 JS 代码放在 src 文件夹后,您就可以使用 npm start 或 npm run start 命令启动开发环境,该环境会监控脚本并在必要时自动重新编译代码。开发完成后,使用 npm build 或 npm run build 命令会将 JavaScript 代码编译到 build 文件夹中,其中将包含为生产而优化的代码。

现在,让我们学以致用,修改上一节中创建的插件,在文章编辑器侧边栏中添加一个新面板,用于管理自定义字段。

如何创建附加侧边栏来管理文章元字段

我们的目标是创建一个自定义侧边栏,其中包含一个面板和一个文本字段,用于添加和编辑自定义元字段。

在开始之前,我们应该提到,我们可以使用自定义元栏来实现同样的效果。在 WordPress 6.7 中,元方框得到了升级,现在可以与区块编辑器完全兼容,所以你可能会问,为什么要用自定义侧边栏而不是元方框来管理元字段。原因是侧边栏允许你利用内置组件。这可以帮助你创建更友好的界面,并提供用户熟悉的强大控件。

下面是创建自定义侧边栏的过程,它允许你在编辑器中管理自定义字段。

my-sidebar-plugin.php

步骤 1:注册文章元

首先,您需要注册元字段。在插件主文件中添加以下代码:

function my_sidebar_plugin_register_meta() {
register_post_meta(
'post',
'meta_fields_book_title', 
array(
'show_in_rest' => true,
'type' => 'string',
'single' => true,
'sanitize_callback' => 'sanitize_text_field',
'label' => __( 'Book title', 'my-sidebar-plugin' ),
'auth_callback' => function() { 
return current_user_can( 'edit_posts' );
}
)
);
}
add_action( 'init', 'my_sidebar_plugin_register_meta' );

register_post_meta 函数接受三个参数:

  • 要注册元关键字的文章类型。如果设置为空字符串,就会在所有现有的文章类型中注册元关键字。
  • 要注册的元键。请注意,我们没有在元键开头使用下划线。在元键前加上下划线会隐藏自定义字段,所以你可能想在元框中使用它。不过,隐藏自定义字段会导致元字段无法通过区块绑定 API 在文章内容中使用。
  • 参数数组。请注意,必须将 show_in_rest 设置为 true。这样就能将元字段公开给 Rest API,并允许我们将元字段绑定到区块属性。有关其他属性,请参阅函数参考

步骤 2:注册元框

为确保插件的向后兼容性,您需要注册一个自定义元框,以便用户即使使用经典编辑器也能管理自定义字段。在插件的 PHP 文件中添加以下代码:

/**
* Register meta box
* 
* @link https://developer.wordpress.org/reference/functions/add_meta_box/
* 
*/
function my_sidebar_plugin_register_meta_box(){
add_meta_box(
'book_meta_box', // Unique ID
__( 'Book details' ), // Box title
'my_sidebar_plugin_meta_box_callback', // Content callback
array( 'post' ), // Post types
'advanced', // context
'default', // priority
array('__back_compat_meta_box' => true) // hide the meta box in Gutenberg
);
}
add_action( 'add_meta_boxes', 'my_sidebar_plugin_register_meta_box' );

现在声明构建表单的回调:

/**
* Build meta box form
* 
* @link https://developer.wordpress.org/reference/functions/wp_nonce_field/
* @link https://developer.wordpress.org/reference/functions/get_post_meta/
* 
*/
function my_sidebar_plugin_meta_box_callback( $post ){
wp_nonce_field( 'my_sidebar_plugin_save_meta_box_data', 'my_sidebar_plugin_meta_box_nonce' );
$title = get_post_meta( $post->ID, 'meta_fields_book_title', true );
?>
<div class="inside">
<p><strong><?php echo __( 'Book title', 'my-sidebar-plugin' ); ?></strong></p>
<p><input type="text" id="meta_fields_book_title" name="meta_fields_book_title" value="<?php echo esc_attr( $title ); ?>" /></p>
</div>
<?php
}

接下来,编写将元字段保存到数据库的函数:

/**
* Save metadata
* 
* @link https://developer.wordpress.org/reference/functions/wp_verify_nonce/
* @link https://developer.wordpress.org/reference/functions/current_user_can/
* @link https://developer.wordpress.org/reference/functions/sanitize_text_field/
* @link https://developer.wordpress.org/reference/functions/update_post_meta/
* 
*/
function my_sidebar_plugin_save_meta_box_data( $post_id ) {
if ( ! isset( $_POST['my_sidebar_plugin_meta_box_nonce'] ) )
return;
if ( ! wp_verify_nonce( $_POST['my_sidebar_plugin_meta_box_nonce'], 'my_sidebar_plugin_save_meta_box_data' ) )
return;
if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE )
return;
if ( ! current_user_can( 'edit_post', $post_id ) )
return;
if ( ! isset( $_POST['meta_fields_book_title'] ) )
return;
$title = sanitize_text_field( $_POST['meta_fields_book_title'] );
update_post_meta( $post_id, 'meta_fields_book_title', $title );
}
add_action( 'save_post', 'my_sidebar_plugin_save_meta_box_data' );

由于超出了本文的讨论范围,我们将不再深入探讨这些代码,但您可以通过函数标题中的链接找到所需的全部信息。

最后,我们需要启动插件的 index.js 文件:

function my_sidebar_plugin_register_script() {
wp_enqueue_script(
'my_sidebar_plugin_script',
plugins_url( 'build/index.js', __FILE__ ),
array( 'wp-plugins', 'wp-edit-post' ),
filemtime( plugin_dir_path( __FILE__ ) . 'build/index.js' )
);
}
add_action( 'enqueue_block_editor_assets', 'my_sidebar_plugin_register_script' );

这就是 PHP 文件的全部内容。接下来,我们需要编写 JS 代码。

index.js

您的index.js位于src文件夹中,该文件夹是您在开发阶段存储 JS 文件的地方。

打开index.js,添加以下 import 声明

import { __ } from '@wordpress/i18n';
import { registerPlugin } from '@wordpress/plugins';
import { PluginSidebar } from '@wordpress/editor';
import { PanelBody, PanelRow, TextControl } from '@wordpress/components';
import { useSelect } from '@wordpress/data';
import { useEntityProp } from '@wordpress/core-data';

您需要使用这些资源来创建带有所需控件的侧边栏。

接下来,您需要构建侧边栏组件:

const MyPluginSidebar = () => {
const postType = useSelect(
( select ) => select( 'core/editor' ).getCurrentPostType(),
[]
);
const [ meta, setMeta ] = useEntityProp( 'postType', postType, 'meta' );
const bookTitle = meta ? meta[ 'meta_fields_book_title' ] : '';
const updateBookTitleMetaValue = ( newValue ) => {
setMeta( { ...meta, meta_fields_book_title: newValue } );
};
if ( postType === 'post' ) {
return (
<PluginSidebar
name="my-sidebar-plugin"
icon="book"
title="My plugin sidebar"
>
<PanelBody title="Book details" initialOpen={ true }>
<PanelRow>
<TextControl 
value={ bookTitle }
label={ __( "Book title" ) }
onChange={ updateBookTitleMetaValue }
__nextHasNoMarginBottom
/>
</PanelRow>
</PanelBody>
</PluginSidebar>
);
}
};
registerPlugin( 'my-sidebar-plugin', {
render: MyPluginSidebar,
} );

registerPlugin 函数用于注册插件并渲染名为 MyPluginSidebar 的组件。

函数 MyPluginSidebar 声明了几个常量,并返回组件的 JSX 代码。

  • useSelect 是一个自定义钩子,用于从已注册的选择器中获取道具。我们用它来获取当前的文章类型。另请参阅 WordPress 开发者博客中的这篇博文
  • useEntityProp 返回一个元字段数组和一个用于设置新元值的 setter 函数。另请参阅在线参考资料
  • updateBookTitleMetaValue 是一个保存 bookTitle 元字段值的事件处理程序。

我们使用了一些内置组件来创建侧边栏:

  • PluginSidebar 允许您在“文章”或“网站”编辑器屏幕的工具栏上添加项目。(请参阅该组件的参考资料。)
  • PanelBody 可创建一个可折叠的容器,并可切换打开或关闭。(请参阅该组件的参考资料。)
  • PanelRowPanelBody 中行的通用容器。(请参阅该组件的参考资料。)
  • TextControl 是一个单行字段,可用于自由输入文本。(请参阅该组件的参考资料。)

现在运行npm run build命令,激活插件,然后创建一个新的文章。顶部侧边栏会出现一个新书图标。点击该图标即可显示插件侧边栏。

带有元字段的自定义侧边栏

带有元字段的自定义侧边栏

如果您不需要新的侧边栏,但想在内置的文章侧边栏中显示自定义字段,该怎么办?您只需将 PluginSidebar 替换为 PluginDocumentSettingPanel 即可。这就是你的新 index.js 文件:

import { __ } from '@wordpress/i18n';
import { registerPlugin } from '@wordpress/plugins';
import { PluginDocumentSettingPanel } from '@wordpress/edit-post';
import { PanelBody, PanelRow, TextControl } from '@wordpress/components';
import { useSelect } from '@wordpress/data';
import { useEntityProp } from '@wordpress/core-data';
const MyPluginSidebar = () => {
const postType = useSelect(
( select ) => select( 'core/editor' ).getCurrentPostType(),
[]
);
const [ meta, setMeta ] = useEntityProp( 'postType', postType, 'meta' );
const bookTitle = meta ? meta[ 'meta_fields_book_title' ] : '';
const updateBookTitleMetaValue = ( newValue ) => {
setMeta( { ...meta, meta_fields_book_title: newValue } );
};
if ( postType === 'post' ) {
return (
<PluginDocumentSettingPanel 
name="my-sidebar-plugin"
title="Book details" 
className="my-sidebar-plugin"
>
<PanelRow>
<TextControl 
value={ bookTitle }
label={ __( "Book title" ) }
onChange={ updateBookTitleMetaValue }
__nextHasNoMarginBottom
/>
</PanelRow>
</PluginDocumentSettingPanel>
);
}
};
registerPlugin( 'my-sidebar-plugin', {
render: MyPluginSidebar,
} );

下图显示了结果。

文章侧边栏中的自定义设置面板

文章侧边栏中的自定义设置面板

实例:区块样板覆盖,实现工作流程自动化

现在,您可以为自定义字段添加一个值,该值可通过区块绑定 API 与区块属性一起使用。例如,您可以在内容中添加一个段落区块,并将自定义字段绑定到段落的 content 属性上。

将元字段绑定到区块属性

将元字段绑定到区块属性

您可以自由更改自定义字段的值,这些更改将自动应用到您的段落内容中。

如果您想知道自定义字段和区块绑定是否还有其他功能,答案是肯定的!通过区块样板和区块绑定 API,您可以自动完成整个内容创建过程。

要获得线索,至少要创建一个包含标题或段落的样板。在本例中,我们创建的区块样板包含一个栏目区块、一个图像、一个标题和几个行区块,每个行区块包含两个段落。

带有一个图片、一个标题和两行的栏目区块

带有一个图片、一个标题和两行的栏目区块

对布局满意后,选择包装元素并创建同步样板。

创建样板

创建样板

为区块样板添加名称和类别,并确保同步。

添加新样板

添加新样板

下一步,如果您在“文章”编辑器中创建了样板,请选择该样板并单击区块工具栏中的“编辑原始”。您也可以导航到网站编辑器的样板部分,在我的样板下或您之前设置的样板类别中找到该样板。

打开代码编辑器,找到要绑定到自定义字段的区块。在区块分隔符中添加以下代码:

<!-- wp:heading {
"metadata":{
"bindings":{
"content":{
"source":"core/post-meta",
"args":{
"key":"meta_fields_book_title"
}
}
}
}
} -->

代码编辑器中的区块样板

代码编辑器中的区块样板

保存样板并创建新文章。将样板添加到内容中,并为自定义字段设置一个值。您会看到该值自动应用到您的样板中。

同步样板中的绑定标题

同步样板中的绑定标题

现在,你可以玩转这个插件了。借助自定义字段和区块绑定 API,您可以添加更多的字段和控件来自动填充布局。

小结

开发自定义区块可能很有挑战性。但是,如果使用区块样板可以做得更多,还需要构建区块吗?

随着区块样板的发展和强大的开发人员功能(如区块绑定 API)的引入,创建自定义区块来构建复杂而实用的网站已不再必要。一个简单的插件和一个区块样板就能有效地自动完成大部分工作流程。

本教程演示了如何通过插件为 WordPress 文章编辑器添加功能。然而,我们在这篇文章中介绍的只是WordPress目前提供的强大功能的皮毛。

您是否已经探索过这些功能并为 WordPress 编辑器添加了功能?如果是,请在下面的评论区分享您的经验和见解。

评论留言