WordPress源码深度解析之:古腾堡的`Block`注册:`register_block_type()`函数的内部工作原理。

咳咳,大家好!今天咱们不聊风花雪月,来点硬核的——古腾堡编辑器里的Block注册机制。别被“深度解析”吓到,我会尽量用大白话把这玩意儿掰开了揉碎了讲清楚,保证你听完之后,下次看到register_block_type(),不再是两眼一抹黑。

开场白:Block,古腾堡的基石

在古腾堡的世界里,一切皆Block。不管是标题、段落、图片,还是什么花里胡哨的自定义组件,最终都得变成一个个Block。而register_block_type()函数,就是让这些Block能在古腾堡里安家落户的关键。

第一部分:register_block_type()函数全方位解剖

register_block_type()函数的作用,简单来说,就是告诉WordPress:“嘿,我这儿有个新的Block,你帮我注册一下,以后有人要用就招呼一声。”

它的基本语法如下:

register_block_type( string $block_name, array|string $args );
  • $block_name:Block的唯一标识符。通常是namespace/block-name的形式,比如my-plugin/fancy-button。这个名字必须是唯一的,否则就等着报错吧!
  • $args:一个数组,包含了Block的各种配置信息,比如编辑器的JS文件、服务器端渲染的回调函数等等。也可以是一个指向block.json文件的字符串,方便简洁。

1.1 $block_name:起个好名字很重要

$block_name不仅仅是一个字符串,它背后蕴含着命名规范和作用域的概念。

  • Namespace: 建议使用你的插件或主题的名称作为Namespace,避免和其他Block冲突。比如,你的插件叫“Awesome Plugin”,那么可以把Block命名为awesome-plugin/my-block
  • Block Name: Block的名字应该具有描述性,让人一看就知道这个Block是干嘛的。比如featured-postimage-gallery等等。

1.2 $args:Block的灵魂

$args数组才是重头戏,它定义了Block的行为、样式和交互。让我们来看看里面有哪些常用的参数:

参数名 类型 描述
attributes array 定义Block的属性,比如文本内容、颜色、图片URL等等。这些属性会被存储到文章内容中。
render_callback callable 一个PHP回调函数,用于在服务器端渲染Block的内容。这对于动态Block(比如显示最新文章)非常有用。
editor_script string 编辑器中使用的JavaScript文件。通常包含Block的编辑界面逻辑。
editor_style string 编辑器中使用的CSS文件。用于定义Block在编辑器中的样式。
style string 前端使用的CSS文件。用于定义Block在网站前台的样式。
script string 前端使用的JavaScript文件。用于处理Block在前台的交互逻辑。
supports array 定义Block支持的功能,比如对齐方式、HTML锚点等等。
provides_context array 定义Block可以提供的上下文信息,供子Block使用。
uses_context array 定义Block需要使用的上下文信息,来自父Block的provides_context
example array 提供一个Block的示例数据,用于在Block面板中显示。
deprecated array 用于处理Block的废弃版本,提供迁移方案。
block.json (string) string 指向 block.json 文件的路径。这是定义 Block 元数据的推荐方式,可以避免在 PHP 代码中编写大量的配置信息。 如果使用 block.json,则不需要传递 $args 数组。

第二部分:block.json——更优雅的Block定义方式

block.json是定义Block元数据的推荐方式。它是一个JSON文件,包含了Block的所有配置信息,可以大大简化PHP代码。

2.1 block.json的基本结构

一个典型的block.json文件可能长这样:

{
  "name": "my-plugin/fancy-button",
  "title": "Fancy Button",
  "description": "A beautiful button with custom styling.",
  "category": "common",
  "icon": "button",
  "keywords": ["button", "link"],
  "attributes": {
    "text": {
      "type": "string",
      "default": "Click Me!"
    },
    "url": {
      "type": "string",
      "default": "#"
    },
    "backgroundColor": {
      "type": "string",
      "default": "blue"
    }
  },
  "supports": {
    "align": true
  },
  "editorScript": "file:./index.js",
  "editorStyle": "file:./editor.css",
  "style": "file:./style.css"
}
  • name:Block的唯一标识符,和register_block_type()的第一个参数一样。
  • title:Block在编辑器中显示的名称。
  • description:Block的描述,用于在Block面板中显示。
  • category:Block所属的类别,比如commonformattinglayout等等。
  • icon:Block的图标,可以在WordPress的Dashicons中选择。
  • keywords:Block的关键词,用于在Block面板中搜索。
  • attributes:定义Block的属性。
  • supports:定义Block支持的功能。
  • editorScript:编辑器中使用的JavaScript文件。 file:协议是WordPress推荐的,它会自动处理文件路径。
  • editorStyle:编辑器中使用的CSS文件。 file:协议是WordPress推荐的,它会自动处理文件路径。
  • style:前端使用的CSS文件。 file:协议是WordPress推荐的,它会自动处理文件路径。

2.2 使用block.json注册Block

有了block.json文件,注册Block就变得非常简单:

register_block_type( __DIR__ . '/block.json' );

只需要传入block.json文件的路径即可。WordPress会自动解析block.json文件,并注册Block。

第三部分:attributes——Block的灵魂数据

attributes定义了Block的数据结构,它们决定了Block能存储哪些信息。

3.1 attributes的结构

attributes是一个对象,每个属性都包含以下信息:

  • type:属性的类型,可以是stringnumberbooleanarrayobject
  • default:属性的默认值。
  • source:属性值的来源,比如htmlattributechildren等等。
  • selector:CSS选择器,用于从HTML中提取属性值。

3.2 常见attributes类型和用法

  • string: 存储文本内容。

    {
      "text": {
        "type": "string",
        "default": "Hello, World!"
      }
    }
  • number: 存储数字。

    {
      "fontSize": {
        "type": "number",
        "default": 16
      }
    }
  • boolean: 存储布尔值。

    {
      "bold": {
        "type": "boolean",
        "default": false
      }
    }
  • array: 存储数组。

    {
      "items": {
        "type": "array",
        "default": []
      }
    }
  • object: 存储对象。

    {
      "style": {
        "type": "object",
        "default": {}
      }
    }

3.3 source属性:数据的来源

source属性定义了如何从HTML中提取属性值。常用的source类型包括:

  • html: 从HTML标签的内容中提取。需要配合selector使用。

    {
      "text": {
        "type": "string",
        "source": "html",
        "selector": "p"
      }
    }
  • attribute: 从HTML标签的属性中提取。需要配合selectorattribute使用。

    {
      "url": {
        "type": "string",
        "source": "attribute",
        "selector": "a",
        "attribute": "href"
      }
    }
  • children: 从HTML标签的子元素中提取。需要配合selector使用。

    {
      "content": {
        "type": "array",
        "source": "children",
        "selector": "p"
      }
    }
  • text: 从HTML标签的文本内容中提取。需要配合selector使用。

        {
          "altText": {
            "type": "string",
            "source": "text",
            "selector": "img"
          }
        }

第四部分:render_callback——服务器端渲染的秘密

render_callback是一个PHP回调函数,用于在服务器端渲染Block的内容。这对于动态Block(比如显示最新文章)非常有用。

4.1 render_callback的基本结构

render_callback函数接收两个参数:

  • $attributes:一个数组,包含了Block的属性值。
  • $content:Block的原始内容,通常是HTML字符串。

render_callback函数应该返回一个HTML字符串,作为Block的最终输出。

4.2 render_callback示例

假设我们要创建一个显示最新文章的Block:

function render_latest_posts( $attributes, $content ) {
  $args = array(
    'posts_per_page' => $attributes['numberOfPosts'],
    'orderby'        => 'date',
    'order'          => 'DESC',
  );

  $query = new WP_Query( $args );

  if ( $query->have_posts() ) {
    $output = '<ul>';
    while ( $query->have_posts() ) {
      $query->the_post();
      $output .= '<li><a href="' . get_permalink() . '">' . get_the_title() . '</a></li>';
    }
    $output .= '</ul>';
    wp_reset_postdata();
    return $output;
  } else {
    return '<p>No posts found.</p>';
  }
}

register_block_type( 'my-plugin/latest-posts', array(
  'attributes'      => array(
    'numberOfPosts' => array(
      'type'    => 'number',
      'default' => 5,
    ),
  ),
  'render_callback' => 'render_latest_posts',
) );

在这个例子中,render_latest_posts函数根据numberOfPosts属性的值,查询最新的文章,并生成一个包含文章标题和链接的HTML列表。

第五部分:editor_scripteditor_style——编辑器的灵魂

editor_scripteditor_style分别指定了编辑器中使用的JavaScript和CSS文件。它们决定了Block在编辑器中的行为和样式。

5.1 JavaScript文件 (editor_script)

JavaScript文件通常包含以下内容:

  • edit函数: 定义Block的编辑界面。这个函数接收一个props对象,包含了Block的属性值和更新函数。
  • save函数: 定义如何将Block的属性值保存到文章内容中。这个函数也接收一个props对象。

5.2 CSS文件 (editor_style)

CSS文件用于定义Block在编辑器中的样式。你可以使用CSS选择器来针对Block的不同元素进行样式设置。

第六部分:实战演练——创建一个简单的按钮Block

现在,让我们来创建一个简单的按钮Block,加深理解。

6.1 创建block.json文件

{
  "name": "my-plugin/custom-button",
  "title": "Custom Button",
  "description": "A simple button with custom text and URL.",
  "category": "common",
  "icon": "button",
  "attributes": {
    "text": {
      "type": "string",
      "default": "Click Here"
    },
    "url": {
      "type": "string",
      "default": "#"
    }
  },
  "editorScript": "file:./index.js",
  "style": "file:./style.css"
}

6.2 创建index.js文件

import { registerBlockType } from '@wordpress/blocks';
import { TextControl, URLInputButton } from '@wordpress/components';
import { useBlockProps } from '@wordpress/block-editor';

registerBlockType('my-plugin/custom-button', {
    edit: (props) => {
        const { attributes, setAttributes } = props;

        return (
            <div {...useBlockProps()}>
                <TextControl
                    label="Button Text"
                    value={attributes.text}
                    onChange={(newText) => setAttributes({ text: newText })}
                />
                <URLInputButton
                    label="Button URL"
                    url={attributes.url}
                    onChange={(newURL) => setAttributes({ url: newURL })}
                />
            </div>
        );
    },
    save: (props) => {
        const { attributes } = props;

        return (
            <a href={attributes.url} className="custom-button">
                {attributes.text}
            </a>
        );
    },
});

6.3 创建style.css文件

.custom-button {
  display: inline-block;
  padding: 10px 20px;
  background-color: #007bff;
  color: #fff;
  text-decoration: none;
  border-radius: 5px;
}

6.4 注册Block

function my_plugin_register_blocks() {
  register_block_type( __DIR__ . '/custom-button/block.json' );
}
add_action( 'init', 'my_plugin_register_blocks' );

将这些文件放到你的插件目录中,激活插件,你就可以在古腾堡编辑器中找到这个自定义按钮Block了。

第七部分:高级技巧

  • Context API: 用于在父Block和子Block之间共享数据。
  • Deprecated Blocks: 用于处理Block的废弃版本,提供迁移方案。
  • Dynamic Blocks: 使用render_callback实现服务器端渲染,创建动态Block。

总结

register_block_type()函数和block.json文件是古腾堡Block注册的核心。理解它们的工作原理,你就可以轻松地创建自定义Block,扩展古腾堡编辑器的功能。 掌握 Block 注册是成为 WordPress 高级开发者的关键一步。

好了,今天的讲座就到这里。希望这些内容能帮助你更好地理解古腾堡的Block注册机制。 下次再见!

发表回复

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