分析 WordPress `gutenberg_block_css_is_active()` 函数的源码:如何判断区块样式是否已加载。

Gutenberg 区块样式:你真的懂它了吗?(源码剖析 gutenberg_block_css_is_active()

大家好,我是老码,今天咱们不聊诗和远方,就聊聊 WordPress Gutenberg 区块样式这档子事儿。很多小伙伴在使用 Gutenberg 编辑器的时候,经常会遇到一个问题:明明我给区块加了自定义样式,但页面上就是不生效,这是为啥呢?

今天,咱们就来扒一扒 WordPress 核心函数 gutenberg_block_css_is_active() 的源码,看看它到底是怎么判断区块样式是否应该加载的,顺便也给大家伙儿理理清 Gutenberg 区块样式加载的整个流程。

准备好了吗?系好安全带,老码要开车了!

一、背景知识:Gutenberg 区块样式加载机制

在深入 gutenberg_block_css_is_active() 之前,咱们先得搞清楚 Gutenberg 区块样式的几种加载方式:

  1. 内联样式(Inline Styles): 直接将 CSS 嵌入到 HTML 元素中。这种方式的优先级最高,但不利于维护和复用。

  2. 嵌入式样式(Embedded Styles): 将 CSS 嵌入到 HTML 文档的 <style> 标签中。这种方式的优先级高于外部样式,但仍然不利于维护和复用。

  3. 外部样式(External Styles): 将 CSS 样式写在单独的 .css 文件中,然后在 HTML 文档中通过 <link> 标签引用。这种方式的优先级最低,但最利于维护和复用。

Gutenberg 区块样式主要采用后两种方式,尤其是外部样式。WordPress 会根据区块的使用情况,动态地加载相应的 CSS 文件。这也就是我们今天要研究的重点。

二、gutenberg_block_css_is_active() 函数源码剖析

好了,废话不多说,直接上代码!

/**
 * Checks if the CSS for a block is active (loaded).
 *
 * @since 5.0.0
 *
 * @param string $name Block name including namespace.
 *
 * @return bool Whether the block CSS is active (loaded).
 */
function gutenberg_block_css_is_active( $name ) {
    global $wp_registered_blocks;

    if ( ! isset( $wp_registered_blocks[ $name ] ) ) {
        return false;
    }

    $block = $wp_registered_blocks[ $name ];

    if ( ! isset( $block->style ) && ! isset( $block->editor_style ) ) {
        return true;
    }

    $handles = array_filter(
        array(
            isset( $block->style ) ? $block->style : null,
            isset( $block->editor_style ) ? $block->editor_style : null,
        )
    );

    foreach ( $handles as $handle ) {
        if ( wp_style_is( $handle, 'queue' ) || wp_style_is( $handle, 'done' ) ) {
            return true;
        }
    }

    return false;
}

现在,咱们一行一行地解读这段代码:

  1. function gutenberg_block_css_is_active( $name ) 定义函数,接收一个参数 $name,表示区块的名称(包含命名空间)。

  2. global $wp_registered_blocks; 声明全局变量 $wp_registered_blocks。这个变量存储了所有已注册的 Gutenberg 区块的信息。

  3. if ( ! isset( $wp_registered_blocks[ $name ] ) ) { return false; } 判断 $wp_registered_blocks 数组中是否存在以 $name 为键的元素。如果不存在,说明该区块没有注册,直接返回 false,表示该区块的 CSS 没有加载。

    • 解释: 这一步非常重要,它确保了我们操作的是一个已经注册的区块。
  4. $block = $wp_registered_blocks[ $name ];$wp_registered_blocks 数组中以 $name 为键的元素赋值给变量 $block$block 变量现在包含了该区块的所有信息,包括其样式信息。

  5. if ( ! isset( $block->style ) && ! isset( $block->editor_style ) ) { return true; } 判断 $block 对象中是否同时不存在 styleeditor_style 属性。如果不存在,说明该区块没有定义任何样式,直接返回 true

    • 解释: 这里有点反直觉,如果区块没有定义任何样式,函数反而返回 true。这是因为 WordPress 认为,如果一个区块没有定义任何样式,那么它就不需要加载任何 CSS 文件,因此可以认为它的“CSS 是激活的”。
  6. $handles = array_filter( array( isset( $block->style ) ? $block->style : null, isset( $block->editor_style ) ? $block->editor_style : null, ) ); 创建一个数组 $handles,其中包含了 $block->style$block->editor_style 的值。然后使用 array_filter() 函数过滤掉数组中的 null 值。

    • 解释:
      • $block->style 表示区块在前端显示的 CSS 样式句柄(handle)。
      • $block->editor_style 表示区块在编辑器中显示的 CSS 样式句柄。
      • array_filter() 用于移除数组中的空值,避免后续处理出现问题。
  7. foreach ( $handles as $handle ) { ... } 遍历 $handles 数组,对每一个样式句柄进行判断。

  8. if ( wp_style_is( $handle, 'queue' ) || wp_style_is( $handle, 'done' ) ) { return true; } 使用 wp_style_is() 函数判断当前样式句柄 $handle 是否已经加入到队列中('queue' 状态)或者已经加载完成('done' 状态)。如果满足其中一个条件,则返回 true,表示该区块的 CSS 已经加载。

    • 解释:
      • wp_style_is( $handle, 'queue' ) 检查样式是否在 WordPress 的样式队列中,等待输出。
      • wp_style_is( $handle, 'done' ) 检查样式是否已经输出到页面上。
      • 如果样式处于这两种状态中的任何一种,就认为这个区块的CSS已经加载了。
  9. return false; 如果遍历完 $handles 数组后,仍然没有找到已经加载的样式句柄,则返回 false,表示该区块的 CSS 没有加载。

三、gutenberg_block_css_is_active() 函数的返回值

总结一下,gutenberg_block_css_is_active() 函数的返回值有三种情况:

返回值 含义
true 区块没有定义任何样式,或者区块的样式已经加入到队列中或者已经加载完成。 简单来说,它会返回true,当没有样式需要加载,或者样式已经成功加载。
false 区块已经注册,并且定义了样式,但是该样式既没有加入到队列中,也没有加载完成。 简单来说,它会返回false,只有在定义了样式但是没有被加载的情况下

四、使用场景举例

  1. 条件加载区块 CSS: 你可以在主题或插件中使用 gutenberg_block_css_is_active() 函数,判断某个区块的 CSS 是否已经加载,然后根据结果决定是否需要手动加载该区块的 CSS。

    if ( ! gutenberg_block_css_is_active( 'my-plugin/my-block' ) ) {
        wp_enqueue_style( 'my-plugin-my-block', plugin_dir_url( __FILE__ ) . 'css/my-block.css' );
    }
  2. 判断区块样式是否生效: 你可以在前端调试时使用 gutenberg_block_css_is_active() 函数,判断某个区块的样式是否已经生效。

    if ( wp.data.select( 'core/blocks' ).isBlockCSSActive( 'my-plugin/my-block' ) ) {
        console.log( 'my-plugin/my-block CSS is active' );
    } else {
        console.log( 'my-plugin/my-block CSS is NOT active' );
    }

五、常见问题及解决方案

  1. 区块样式不生效: 如果你的区块样式不生效,首先要检查你的区块是否已经正确注册。然后,检查你的 CSS 文件是否已经正确加载。你可以使用浏览器的开发者工具来检查 CSS 文件是否加载成功,以及 CSS 规则是否被正确应用。

  2. 重复加载区块 CSS: 如果你发现某个区块的 CSS 被重复加载,可能是因为你在多个地方都手动加载了该区块的 CSS。你可以使用 gutenberg_block_css_is_active() 函数来避免重复加载。

  3. 编辑器样式和前端样式不一致: 如果你发现区块在编辑器中的样式和在前端显示的样式不一致,可能是因为你使用了不同的 CSS 文件来定义编辑器样式和前端样式。你可以使用 $block->editor_style$block->style 属性来分别指定编辑器样式和前端样式的句柄。

六、总结与展望

gutenberg_block_css_is_active() 函数是 WordPress Gutenberg 编辑器中一个非常重要的函数,它可以帮助我们判断区块样式是否已经加载。通过深入理解该函数的源码,我们可以更好地控制 Gutenberg 区块样式的加载,避免出现样式不生效或重复加载等问题。

希望今天的分享对大家有所帮助。记住,理解源码是解决问题的关键。下次遇到 Gutenberg 区块样式的问题,不妨回头看看这段代码,也许你会发现新的灵感!

好了,今天的讲座就到这里。下次有机会,老码再和大家聊聊 Gutenberg 区块开发的更多技巧。

祝大家编程愉快!

发表回复

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