阐述 WordPress `gutenberg_widgets_init` 钩子源码:在小工具编辑器初始化时执行的逻辑。

各位好,我是老码农,今天咱们来聊聊 WordPress 里一个挺有意思的钩子:gutenberg_widgets_init。这玩意儿就像个神秘的幕后推手,专门负责在 Gutenberg 小工具编辑器初始化的时候搞事情。别看名字挺长,其实功能很简单,就是给你一个机会,在小工具编辑器启动前,注册一些自定义的区块或者搞一些初始化设置。

咱们先来缕清一下思路:啥是 Gutenberg 小工具编辑器?为啥需要这么个钩子?它到底能干啥?

啥是 Gutenberg 小工具编辑器?

简单来说,自从 WordPress 5.8 之后,小工具界面就被 Gutenberg 编辑器给接管了。以前那种拖拽式的界面,现在变成了区块式的编辑方式。你可以把小工具想象成一个个独立的区块,像搭积木一样把它们组装起来。这种方式的好处是更加灵活,你可以使用 Gutenberg 编辑器的各种高级功能,比如调整布局、添加样式等等。

为啥需要 gutenberg_widgets_init 钩子?

Gutenberg 编辑器很强大,但默认情况下,它只提供了一些基本的区块。如果你想在小工具编辑器里使用自定义的区块,或者想对编辑器进行一些定制,就需要 gutenberg_widgets_init 钩子来帮忙了。它就像一个入口,让你有机会在编辑器启动前,把自己需要的东西注册进去。

gutenberg_widgets_init 钩子到底能干啥?

  • 注册自定义区块: 这是最常见也是最重要的用途。你可以使用 register_block_type() 函数注册自己的区块,然后在小工具编辑器里使用。
  • 注册区块样式: 如果你想为现有的区块添加一些自定义的样式选项,可以使用 register_block_style() 函数。
  • 添加编辑器脚本和样式: 你可以使用 wp_enqueue_scripts()wp_enqueue_style() 函数,在编辑器中加载自定义的 JavaScript 和 CSS 文件。
  • 移除默认区块: 如果你觉得某些默认区块没用,可以使用 unregister_block_type() 函数把它们移除掉。

好,概念搞清楚了,咱们开始深入源码,看看这个钩子到底是怎么工作的。

gutenberg_widgets_init 钩子的源码位置

gutenberg_widgets_init 钩子是在 wp-includes/widgets.php 文件中定义的。具体的位置在 wp_use_widgets_block_editor() 函数里。

function wp_use_widgets_block_editor() {
    // ... 一些检查条件 ...

    /**
     * Fires when initializing the widgets block editor.
     *
     * @since 5.8.0
     */
    do_action( 'gutenberg_widgets_init' );

    // ... 其它代码 ...
}

可以看到,do_action( 'gutenberg_widgets_init' ) 这行代码就是触发这个钩子的关键。当 WordPress 初始化小工具编辑器时,会执行这个函数,从而触发 gutenberg_widgets_init 钩子,让所有挂载到这个钩子上的函数都执行一遍。

如何使用 gutenberg_widgets_init 钩子?

使用 gutenberg_widgets_init 钩子非常简单,只需要使用 add_action() 函数把你的自定义函数挂载到这个钩子上即可。

add_action( 'gutenberg_widgets_init', 'my_custom_widgets_init' );

function my_custom_widgets_init() {
    // 在这里写你的代码
}

现在,所有写在 my_custom_widgets_init() 函数里的代码,都会在小工具编辑器初始化时执行。

实战演练:注册一个自定义区块

咱们来写一个简单的例子,注册一个名为 my-plugin/hello-world 的自定义区块,这个区块只显示 "Hello World!" 这几个字。

  1. 创建一个插件文件:

    wp-content/plugins 目录下创建一个名为 my-plugin 的文件夹,然后在里面创建一个 my-plugin.php 文件。

  2. 编写插件代码:

    <?php
    /**
     * Plugin Name: My Custom Widgets
     * Description: A plugin to register custom widgets blocks.
     * Version: 1.0.0
     * Author: Old Programmer
     */
    
    add_action( 'gutenberg_widgets_init', 'my_custom_widgets_init' );
    
    function my_custom_widgets_init() {
        register_block_type( __DIR__ . '/blocks/hello-world/block.json' );
    }
    
    add_action( 'init', 'my_register_block' );
    function my_register_block() {
        wp_register_script(
            'my-plugin-hello-world-block',
            plugins_url( 'blocks/hello-world/index.js', __FILE__ ),
            array( 'wp-blocks', 'wp-element', 'wp-editor' ),
            filemtime( plugin_dir_path(__FILE__) . 'blocks/hello-world/index.js' )
        );
    
        register_block_type( 'my-plugin/hello-world', array(
            'editor_script' => 'my-plugin-hello-world-block'
        ) );
    }
  3. 创建区块定义文件:

    my-plugin 目录下创建一个名为 blocks 的文件夹,然后在里面创建一个名为 hello-world 的文件夹。在 hello-world 文件夹里创建一个 block.json 文件,内容如下:

    {
        "name": "my-plugin/hello-world",
        "title": "Hello World",
        "description": "A simple Hello World block.",
        "category": "widgets",
        "icon": "smiley",
        "supports": {
            "html": false
        },
        "attributes": {},
        "textdomain": "my-plugin",
        "editorScript": "file:./index.js",
        "render": "file:./render.php"
    }

    这个 block.json 文件定义了区块的各种属性,比如名称、标题、描述、图标等等。

  4. 编写区块 JavaScript 代码 (index.js):

    import { registerBlockType } from '@wordpress/blocks';
    import { useBlockProps } from '@wordpress/block-editor';
    
    registerBlockType( 'my-plugin/hello-world', {
        title: 'Hello World Block',
        icon: 'smiley',
        category: 'widgets',
        edit: () => {
            return (
                <p { ...useBlockProps() }>Hello World!</p>
            );
        },
        save: () => {
            return (
                <p { ...useBlockProps.save() }>Hello World!</p>
            );
        },
    } );
    
  5. 编写区块渲染 PHP 代码 (render.php):

    <?php
    /**
     * All of the blocks render callback function.
     *
     * @package GutenbergLessons
     */
    
    ?>
    <p <?php echo get_block_wrapper_attributes(); ?>>Hello World! From PHP</p>

    这个 render.php 文件定义了区块在前端如何渲染。

现在,激活你的插件,然后打开小工具编辑器,你就可以看到一个名为 "Hello World" 的自定义区块了。把它拖到小工具区域,保存,然后在前端页面上就可以看到 "Hello World!" 这几个字了。

实战演练:注册区块样式

除了注册新的区块,你还可以为现有的区块注册自定义的样式。比如,你想为段落区块添加一个 "red-paragraph" 的样式,让段落的文字变成红色,可以这样做:

add_action( 'gutenberg_widgets_init', 'my_custom_widgets_init' );

function my_custom_widgets_init() {
    register_block_style(
        'core/paragraph', // 要添加样式的区块名称
        array(
            'name'         => 'red-paragraph', // 样式名称
            'label'        => 'Red Paragraph', // 样式标签
            'is_default'   => false, // 是否为默认样式
        )
    );
}

add_action( 'enqueue_block_editor_assets', 'my_custom_block_editor_assets' );

function my_custom_block_editor_assets() {
    wp_enqueue_style(
        'my-custom-block-styles',
        plugins_url( 'assets/css/block-styles.css', __FILE__ )
    );
}

然后在你的 CSS 文件 assets/css/block-styles.css 中添加以下代码:

.wp-block-paragraph.is-style-red-paragraph {
    color: red;
}

现在,打开小工具编辑器,选择一个段落区块,在右侧的样式选项中,你就可以看到一个名为 "Red Paragraph" 的样式了。选择这个样式,段落的文字就会变成红色。

进阶技巧:移除默认区块

如果你觉得某些默认区块没用,可以使用 unregister_block_type() 函数把它们移除掉。比如,你想移除 "core/archives" 区块,可以这样做:

add_action( 'gutenberg_widgets_init', 'my_custom_widgets_init' );

function my_custom_widgets_init() {
    unregister_block_type( 'core/archives' );
}

现在,打开小工具编辑器,你就会发现 "core/archives" 区块已经不见了。

一些注意事项

  • 钩子执行的时机: gutenberg_widgets_init 钩子是在小工具编辑器初始化时执行的,所以你的代码必须在这个钩子触发之前加载。通常情况下,把你的代码放在插件文件里就可以了。
  • 区块名称的唯一性: 注册区块时,区块的名称必须是唯一的,否则会发生冲突。建议使用 your-plugin-name/block-name 的格式来命名你的区块。
  • 错误处理: 在编写代码时,要做好错误处理,避免因为代码错误导致小工具编辑器无法正常工作。
  • 性能优化: 如果你的代码比较复杂,要注意性能优化,避免影响小工具编辑器的加载速度。

总结

gutenberg_widgets_init 钩子是一个非常强大的工具,可以让你在 WordPress 小工具编辑器中做很多事情。你可以使用它注册自定义区块,添加自定义样式,甚至移除默认区块。只要你掌握了它的用法,就可以打造出更加个性化、更加强大的小工具编辑器。

表格总结:gutenberg_widgets_init 钩子常用函数

函数名 作用 示例
register_block_type() 注册一个自定义区块 register_block_type( __DIR__ . '/blocks/hello-world/block.json' );
register_block_style() 为现有区块注册一个自定义样式 register_block_style( 'core/paragraph', array( 'name' => 'red-paragraph', 'label' => 'Red Paragraph' ) );
unregister_block_type() 移除一个默认区块 unregister_block_type( 'core/archives' );
wp_enqueue_script() 在编辑器中加载 JavaScript 文件 wp_enqueue_script( 'my-custom-block-script', plugins_url( 'assets/js/block.js', __FILE__ ), array( 'wp-blocks', 'wp-element' ) );
wp_enqueue_style() 在编辑器中加载 CSS 文件 wp_enqueue_style( 'my-custom-block-styles', plugins_url( 'assets/css/block-styles.css', __FILE__ ) );
plugins_url() 获取插件目录下的文件 URL plugins_url( 'assets/js/block.js', __FILE__ )
__DIR__ 获取当前文件所在的目录 __DIR__ . '/blocks/hello-world/block.json'

代码示例:完整的插件代码

<?php
/**
 * Plugin Name: My Custom Widgets
 * Description: A plugin to register custom widgets blocks and styles.
 * Version: 1.0.0
 * Author: Old Programmer
 */

add_action( 'gutenberg_widgets_init', 'my_custom_widgets_init' );

function my_custom_widgets_init() {
    // 注册自定义区块
    register_block_type( __DIR__ . '/blocks/hello-world/block.json' );

    // 注册区块样式
    register_block_style(
        'core/paragraph',
        array(
            'name'         => 'red-paragraph',
            'label'        => 'Red Paragraph',
            'is_default'   => false,
        )
    );

    // 移除默认区块
    //unregister_block_type( 'core/archives' );
}

add_action( 'enqueue_block_editor_assets', 'my_custom_block_editor_assets' );

function my_custom_block_editor_assets() {
    wp_enqueue_style(
        'my-custom-block-styles',
        plugins_url( 'assets/css/block-styles.css', __FILE__ )
    );
}

add_action( 'init', 'my_register_block' );
function my_register_block() {
    wp_register_script(
        'my-plugin-hello-world-block',
        plugins_url( 'blocks/hello-world/index.js', __FILE__ ),
        array( 'wp-blocks', 'wp-element', 'wp-editor' ),
        filemtime( plugin_dir_path(__FILE__) . 'blocks/hello-world/index.js' )
    );

    register_block_type( 'my-plugin/hello-world', array(
        'editor_script' => 'my-plugin-hello-world-block'
    ) );
}

别忘了创建 block.jsonindex.js, render.phpassets/css/block-styles.css 文件,并根据你的需求修改内容。

好了,今天的讲座就到这里。希望这些内容能帮助你更好地理解 gutenberg_widgets_init 钩子,并在 WordPress 小工具编辑器中大展身手。 记住,代码的世界,没有最好,只有更好。 多尝试,多学习,你也能成为编程高手!

发表回复

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