adapt your plugin for gutenberg block api

如何为古腾堡调整您的插件:第一部分(区块 API)

“我有一个插件,” 你说,“我如何让它支持古腾堡?”

这个故事很简单;Gutenberg 是 WordPress 的新编辑器体验,将在下一个大版本中合并到核心中。很多不跟上这一变化的插件将会变得过时。这使得在太晚之前为古腾堡调整您的插件变得至关重要。

谁会受到影响?

几乎所有与文章编辑器相关的插件都会受到古腾堡的影响。例如,如果您的插件在 TinyMCE 中添加了一个按钮来在编辑器中放置一个简码,坏消息;它将走到尽头。

adapt your plugin for gutenberg block api

“我需要为古腾堡调整我的插件吗?”

那么哪些插件需要为古腾堡更新?任何以下类型的插件:

  • 自定义元数据框
  • 简码
  • 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

您可以将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 短代码会渲染一个包含您的文本和一条发送推文按钮的推文框。如下所示:

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-tweetclick-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组件在选择区块时添加一个侧边栏。类似于这样:

Gutenberg Inspector Controls

我们还将使用TextareaControlTextControl来为我们的检查器区域添加文本区域和文本输入字段。

我们将在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>

如前所述,我们正在从代码中移除超链接,因为不需要在后端显示它。这将使我们的区块看起来像这样:

Gutenberg Click to Tweet Inspector Controls

区块检查器可以是您区块的强大工具。如果您的插件有太复杂而无法在编辑器区域显示的高级选项,可以将它们放在检查器区域。

我们将在下一节为区块添加最后一个选项来完成JavaScript部分。

区块工具栏

区块工具栏是另一个我们可以用来为区块添加更多选项的预构建UI组件。当您选择区块时,它将出现在区块上方。例如:

Gutenberg Block Toolbar

理想情况下,区块工具栏应该包含区块的主要控件,而检查器则承载次要控件。然而,这一点存在争议,取决于您的具体区块。

我们将使用区块工具栏区域来托管我们的备用样式控件。

与区块检查器类似,我们需要在返回语句中添加以下代码来为区块添加工具栏:

!! 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>
),

我们使用BlockControlsToolbar组件为区块添加工具栏。与区块检查器类似,props.isSelected确保只有当我们的区块获得焦点时工具栏才会显示。

我们还使用TooltipButton组件来实现我们的控件。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 有任何问题,请在评论中提出!

分享你的喜爱

留下评论

您的邮箱地址不会被公开。 必填项已用 * 标注