“我有一个插件,” 你说,“我如何让它支持古腾堡?”
这个故事很简单;Gutenberg 是 WordPress 的新编辑器体验,将在下一个大版本中合并到核心中。很多不跟上这一变化的插件将会变得过时。这使得在太晚之前为古腾堡调整您的插件变得至关重要。
谁会受到影响?
几乎所有与文章编辑器相关的插件都会受到古腾堡的影响。例如,如果您的插件在 TinyMCE 中添加了一个按钮来在编辑器中放置一个简码,坏消息;它将走到尽头。

“我需要为古腾堡调整我的插件吗?”
那么哪些插件需要为古腾堡更新?任何以下类型的插件:
- 自定义元数据框
- 简码
- TinyMCE 按钮
- 或任何编辑器功能
如果您的插件属于以上类别,可能是时候 建立一个功能请求系统 了,因为虽然有些插件仍然可以与古腾堡一起工作,比如一个添加简单元数据框的插件,但用户的体验不会那么流畅。
即使简码会像以前一样继续工作,但它在编辑器中只是一个纯文本节点,而所有用于古腾堡的简码 插件 都将遵循其区块 UI,对用户来说更容易使用。
所以是的,用户会更喜欢为古腾堡体验精心制作的插件。而那些落后的插件将被竞争对手的插件取代。
只是为了让您了解一下,以下是我们一个插件的用户旧编辑器体验的示例 (a),然后是它在古腾堡中的样子 (b) – 该插件已为其进行了优化。
(a)
(b)
别担心!我们将帮助您使您的插件支持古腾堡。有很多方法可以将您的插件集成到古腾堡中,这取决于您插件的工作方式,我们将在本文中讨论这些问题。
值得事先了解的事项
古腾堡是基于 React 编写的。古腾堡插件是用 JavaScript 编写的,对于只使用 PHP 开发的开发者来说,这可能是一个艰难的过渡。虽然您不需要具备 React 知识来为古腾堡制作插件,但您需要一些基本的 JavaScript 理解。如果您之前使用过 React 和 JSX,那么这对您来说会是类似的领域。
虽然古腾堡的官方文档不够充分,但其 GitHub 仓库有很多对开发者有价值的信息。如果您想深入学习古腾堡开发,您必须密切关注古腾堡 GitHub 仓库中发生的一切,因为项目发展非常快,每天都在变化。
如何为古腾堡调整您的插件
古腾堡的 API 为我们提供了多种扩展编辑器的方法,如区块 API、简码 API 等。使用哪种 API 取决于我们正在构建的插件类型。
如果您的插件是一个简单的简码插件,那么可以使用区块 API 为编辑器制作一个漂亮的区块。但如果您的插件使用复杂的元数据框,一个区块不够用,我们可以使用侧边栏 API。
此外,我们还将使用现代的 JavaScript 开发工具栈,如 NodeJS、NPM、webpack 和 ESNext。我们将为您提供示例文件,这样您就不必担心设置开发环境了。
在本文中,我们将介绍如何使用 Block API 让您的插件兼容 Gutenberg。如有必要,我们将在第二部分介绍其他方法(Sidebar API、发布面板、状态栏及类似的 API)。
您可以在this GitHub 仓库中找到所有提到的示例。
Gutenberg 开发环境
开发 Gutenberg 需要您配置一系列工具,例如 NPM、webpack、Babel 和 JSX。这需要大量时间和精力,因此我们为您准备好了开发环境。
Gutenberg Boilerplate 是一个包含最小化 Gutenberg 开发设置和示例的插件。它包含一个块和侧边栏示例。您可以将其扩展为您的自定义块。

您可以将Gutenberg Boilerplate 仓库克隆或 Fork 到您的 /wp-content/plugins/ 目录中,并将其用作开发环境。
之后,您需要安装 NodeJS 来开始开发。导航到 Gutenberg Boilerplate 文件夹,然后运行 npm install
从现在开始,您需要了解在开发过程中会使用的三个命令:
npm install– 克隆项目时安装项目依赖。npm run dev– 在开发过程中编译代码。您只需运行一次,它将持续监视更改。npm run build– 开发完成后编译优化版本的代码。
Block API
块是 Gutenberg 的基本元素,它是一个基于块的编辑器。Block API 允许您为 Gutenberg 创建块。您可以创建能够渲染基本 HTML、短代码的块,甚至可以创建动态块来显示例如您的最新文章。
基于现有插件的流程
在我们的示例中,我们将把 Click to Tweet 短代码适配为 Gutenberg 块。此 Click to Tweet 短代码会渲染一个包含您的文本和一条发送推文按钮的推文框。如下所示:

我们的短代码如下所示:
[clicktotweet tweet="Text to be displayed" tweetsent="Text to be tweeted" button="Tweet" theme="click-to-tweet"]
我们的短代码有四个参数:
tweet:显示在您网站上的文本。tweetsent:发送到 Twitter 的文本。button:推文按钮文本。theme:盒子主题,可以是click-to-tweet或click-to-tweet-alt。
使用 Block API 为 Gutenberg 适配插件
在 Gutenberg 中有两种方式:要么我们在前端渲染 HTML,要么使用我们的 Gutenberg 块来渲染短代码到前端。在本文中,我们将采用后一种方式。
所有代码都可在 GitHub 上的 Hello Gutenberg 插件仓库中找到。您可以克隆该仓库以查看插件的实际效果,或修改代码。
为 Gutenberg 入队脚本/样式
首先,我们需要使用 enqueue_block_assets 将我们的脚本和样式入队到 Gutenberg 编辑器中:
/**
* Enqueue front end and editor JavaScript and CSS
*/
function hello_gutenberg_scripts() {
$blockPath = '/dist/block.js';
$stylePath = '/dist/block.css';
// Enqueue the bundled block JS file
wp_enqueue_script(
'hello-gutenberg-block-js',
plugins_url( $blockPath, __FILE__ ),
[ 'wp-i18n', 'wp-blocks', 'wp-editor', 'wp-components' ],
filemtime( plugin_dir_path(__FILE__) . $blockPath )
);
// Enqueue frontend and editor block styles
wp_enqueue_style(
'hello-gutenberg-block-css',
plugins_url( $stylePath, __FILE__ ),
'',
filemtime( plugin_dir_path(__FILE__) . $stylePath )
);
}
// Hook scripts function into block editor hook
add_action( 'enqueue_block_assets', 'hello_gutenberg_scripts' );
我们已经为脚本添加了四个依赖项,这些依赖项将在我们的块中使用。让我们先了解一下这些依赖项:
wp-i18n 是 Gutenberg 的国际化函数版本,例如 __()。wp-blocks 用于 registerBlockType 函数,该函数用于注册你的块。我们使用 wp-editor 和 wp-components 脚本来提供块中的各种组件。
现在我们已经加载了资源,可以开始在 /src/block.js 文件中编写我们的块了。
导入依赖项
如果你使用的是 Gutenberg Boilerplate,那么你的 block.js 文件应该有一个基本的块结构,你可以用它来为 Gutenberg 构建插件:
/**
* Internal block libraries
*/
const { __ } = wp.i18n;
const { registerBlockType } = wp.blocks;
/**
* Register block
*/
export default registerBlockType( 'gutenberg-boilerplate/block', {
// Block Title
title: __( 'Gutenberg Boilerplate' ),
// Block Description
description: __( 'An example block.' ),
// Block Category
category: 'common',
// Block Icon
icon: 'admin-site',
// Block Keywords
keywords: [
__( 'Boilerplate' ),
__( 'Hello World' ),
__( 'Example' ),
],
attributes: {
},
// Defining the edit interface
edit: props => {
return (
<h2>{ __( 'Hello Backend' ) }</h2>
);
},
// Defining the front-end interface
save: props => {
return (
<h2>{ __( 'Hello Frontend' ) }</h2>
);
},
});
你可以运行 npm run dev 来实时编译我们的代码。
首先,我们将在顶部导入块所需的所有组件和库:
/**
* Block dependencies
*/
import classnames from 'classnames';
/**
* Internal block libraries
*/
const { __ } = wp.i18n;
const { registerBlockType } = wp.blocks;
const {
RichText,
InspectorControls,
BlockControls,
} = wp.editor;
const {
PanelBody,
TextareaControl,
TextControl,
Dashicon,
Toolbar,
Button,
Tooltip,
} = wp.components;
首先导入的是 classnames,这是我们用 npm 安装的,用于在代码中使用多个类,因为 JSX 不允许元素有多个类。
随着我们使用它们,我们会了解其他导入的组件。
定义属性
现在我们将为我们的 Gutenberg 块定义四个属性,与我们的短代码相同:
attributes: {
tweet: {
type: 'string',
},
tweetsent: {
type: 'string',
},
button: {
type: 'string',
default: __( 'Tweet' ),
},
theme: {
type: 'boolean',
default: false,
},
},
如你所见,所有属性都与我们的短代码相同。所有属性都有一个 type 键,告诉 Gutenberg 它的数据类型。你可以使用 string、number、boolean 和 object 作为接受的类型。
某些属性还包含默认值。属性也可以有其他属性,如 source 和 selector,在这个例子中我们不会使用,但你可以在这里了解更多。
编辑界面
现在我们将构建块的编辑界面,这是用户将在 Gutenberg 中编辑块时看到的显示。
为了获得基本概念,我们首先可以硬编码我们的块,并通过替换代码中的以下区域来构建它:
// Defining the edit interface
edit: props => {
return (
<h2>{ __( 'Hello Backend' ) }</h2>
);
},
使用以下代码:
// 定义编辑界面
edit: props => {
return [
<div className={ props.className }>
<div className="click-to-tweet">
<div className="ctt-text">南瓜和企鹅</div>
<p><a href="https://twitter.com/intent/tweet?text=Pumpkins%20and%20Penguins" className="ctt-btn">发推</a></p>
</div>
</div>
];
},
这能让您了解我们的最终结果。它看起来会像这样:
区块的第一个元素是推文文本区域。我们将用一个可编辑的文本字段替换它,类似于Gutenberg的标题块。
我们将使用RichText组件(之前已导入)来替换我们的硬编码文本。
<div className="ctt-text">
<RichText
format="string"
formattingControls={ [] }
placeholder={ __( '推文,推文!' ) }
onChange={ onChangeTweet }
value={ props.attributes.tweet }
/>
</div>
我们的RichText组件有五个参数。format是一个字符串,因为我们将在前端使用短代码来显示元素。如果我们想在属性中使用选择器,那么format应该是一个数组。
RichText有一些默认的格式化选项,比如粗体和斜体,我们通过在formattingControls参数中传递一个空数组来禁用它们。
placeholder是字段中没有文本时的占位文本,onChange将在发生更改事件时触发onChangeTweet函数。
最后,value将是我们字段的值,它取自我们之前定义的tweet属性。
一旦我们定义了RichText区域,就需要构建onChangeTweet函数,当文本字段中的值发生变化时将触发该函数。
// 定义编辑界面
edit: props => {
const onChangeTweet = value => {
props.setAttributes( { tweet: value } );
};
return [
...rest of the code
我们将RichText字段的值传递给onChangeTweet函数,该函数使用props.setAttributes函数来更新tweet属性的值。
现在您将在使用区块时看到Gutenberg的强大之处。
是不是很棒?
区块检查器
为Gutenberg构建插件时,您不需要每次都重新发明轮子来为您的插件制作选项面板。Gutenberg为我们提供了一种简化的方式来允许区块自定义,并确保每个用户都能获得与内置UI模式一致的使用体验。
与RichText组件类似,InspectorControls组件在选择区块时添加一个侧边栏。类似于这样:

我们还将使用TextareaControl和TextControl来为我们的检查器区域添加文本区域和文本输入字段。
我们将在return语句中添加以下代码:
!! props.isSelected && (
<InspectorControls key="inspector">
<PanelBody title={ __( '推文设置' ) } >
<TextareaControl
label={ __( '推文文本' ) }
value={ props.attributes.tweetsent }
onChange={ onChangeTweetSent }
help={ __( '您可以在此处添加将成为实际推文一部分的标签和提及,但不会显示在您的文章中。' ) }
/>
<TextControl
label={ __( '按钮文本' ) }
value={ props.attributes.button }
onChange={ onChangeButton }
/>
</PanelBody>
</InspectorControls>
),
props.isSelected检查以确保仅在选择区块时检查器才会出现。
TextareaControl和TextControl组件与RichText类似,具有value和onChange方法。
我们还需要更改区块显示的代码以适应新的变化。在我们的案例中,我们只需要将按钮文本添加到我们的区块中,因为推文文本将被添加到链接中,所以我们不需要在后端显示它。
您可以用以下代码替换初始代码中的超链接:
<a className="ctt-btn">
{ props.attributes.button }
</a>
如前所述,我们正在从代码中移除超链接,因为不需要在后端显示它。这将使我们的区块看起来像这样:

区块检查器可以是您区块的强大工具。如果您的插件有太复杂而无法在编辑器区域显示的高级选项,可以将它们放在检查器区域。
我们将在下一节为区块添加最后一个选项来完成JavaScript部分。
区块工具栏
区块工具栏是另一个我们可以用来为区块添加更多选项的预构建UI组件。当您选择区块时,它将出现在区块上方。例如:

理想情况下,区块工具栏应该包含区块的主要控件,而检查器则承载次要控件。然而,这一点存在争议,取决于您的具体区块。
我们将使用区块工具栏区域来托管我们的备用样式控件。
与区块检查器类似,我们需要在返回语句中添加以下代码来为区块添加工具栏:
!! props.isSelected && (
<BlockControls key="custom-controls">
<Toolbar
className='components-toolbar'
>
<Tooltip text={ __( 'Alternative Design' ) }>
<Button
className={ classnames(
'components-icon-button',
'components-toolbar__control',
{ 'is-active': props.attributes.theme },
) }
onClick={ toggletheme }
>
<Dashicon icon="tablet" />
</Button>
</Tooltip>
</Toolbar>
</BlockControls>
),
我们使用BlockControls和Toolbar组件为区块添加工具栏。与区块检查器类似,props.isSelected确保只有当我们的区块获得焦点时工具栏才会显示。
我们还使用Tooltip和Button组件来实现我们的控件。Tooltip组件包裹在Button组件周围,以确保当您悬停在控件上时会显示工具提示,为您提供更多上下文。
Button组件使用了我们之前在文章中导入的classnames模块。我们使用classnames函数为控件添加了三个类。第三个类is-active只会在我们的theme属性值为true时出现。
它的onChange函数将theme属性切换为true/false。最后,Dashicon组件用于显示控件的图标。
我们还必须更改区块代码以使其与更改配合使用。我们需要替换以下行:
<div className="click-to-tweet">
改为:
<div className={ ( props.attributes.theme ? 'click-to-tweet-alt' : 'click-to-tweet' ) }>
我们检查theme属性是true还是false,并相应地为我们的区块分配类。
现在您的区块应该看起来像这样:
我们已完成Gutenberg区块的JavaScript端部分。您可以在此处找到整个文件的源代码。
现在我们将通过处理服务器端输出来完成我们的区块。
服务器端渲染
Gutenberg允许您使用服务器端渲染来在前端显示您的区块。服务器端渲染使我们能够为短代码创建区块。
首先,我们将通过替换以下代码使我们的save方法返回null:
// Defining the front-end interface
save() {
// Rendering in PHP
return null;
},
我们将使用register_block_type PHP函数在PHP中注册我们的区块类型:
if ( function_exists( 'register_block_type' ) ) {
// Hook server side rendering into render callback
register_block_type(
'hello-gutenberg/click-to-tweet', [
'render_callback' => 'hello_gutenberg_block_callback',
'attributes' => array(
'tweet' => array(
'type' => 'string',
),
'tweetsent' => array(
'type' => 'string',
),
'button' => array(
'type' => 'string',
'default' => 'Tweet',
),
'theme' => array(
'type' => 'boolean',
'default' => false,
),
),
]
);
}
我们的 register_block_type 函数。首先我们向它传递块名称,以及一个参数数组。
第一个参数是 render_callback 函数,它调用我们的 hello_gutenberg_block_callback 函数进行服务器端渲染。
在我们的渲染回调之后,我们传递一个属性数组,类似于 block.js 文件,我们在渲染回调函数中使用它。
我们的渲染回调函数如下所示:
function hello_gutenberg_block_callback( $attr ) {
extract( $attr );
if ( isset( $tweet ) ) {
$theme = ( $theme === true ? 'click-to-tweet-alt' : 'click-to-tweet' );
$shortcode_string = '[clicktotweet tweet="%s" tweetsent="%s" button="%s" theme="%s"]';
return sprintf( $shortcode_string, $tweet, $tweetsent, $button, $theme );
}
}
我们提取所有属性,然后将它们返回到我们的短代码中。这就是将短代码插件适配到 Gutenberg 所需要的全部内容。
您可以在此 hello-gutenberg 仓库中找到本文中使用的所有代码。
在下一部分中,我们将探讨其他将现有插件适配到 Gutenberg 的方法,包括 Sidebar API。
进一步阅读:
查看我们的其他 API 教程:
如果您对如何将插件适配到 Gutenberg 有任何问题,请在评论中提出!



