WordPress 6.4 引入了区块钩子(Block Hooks) ( #53987 ),该功能为块主题提供了可扩展性机制。这是模拟 WordPress 的Hooks概念的第一步, 该概念允许开发人员使用过滤器和操作来扩展经典主题。
具体来说,Block Hooks API允许块相对于其他块类型的实例自动插入自身。例如,“喜欢”按钮块可以要求插入到帖子内容块之前,或者电子商务购物车块可以要求插入到导航块之后。
原则和当前限制
Block Hooks有两个核心原则:
- 一旦包含挂钩块的插件被激活,前端插入就应该发生。换句话说,用户不需要在编辑器中手动插入块。同样,禁用插件应该从前端删除挂钩块。
- 用户对任何自动插入的块拥有最终控制权。这意味着挂钩的块在编辑器中可见,并且用户保留、删除、自定义或移动该块的决定将受到尊重并反映在前端。
为了兼顾这两个原则,必须进行权衡。块挂钩仅限于模板、模板部分和样板(即定义主题布局的元素)。对于样板(patterns),这包括由主题、来自 Block Pattern Directory或对 register_block_pattern 的调用提供的样板。
区块无法挂钩到用户制作的帖子内容或样板,例如同步样板或用户已修改的主题模板和模板部分。
此外,从 WordPress 6.4 开始,您无法自动插入具有保存功能的块,否则会出现块验证错误。用通俗的话说,这意味着块钩子与动态块一起工作,而不是静态块。关于两者的区别可以参考这篇文章。
使用区块钩子
您可以通过两种不同的方式实现块钩子:在块的block.json文件中或使用新的hooked_block_types 过滤器。虽然更简单,但该block.json方法提供了更有限的实现,因此让我们首先回顾一下。
block.json
这种block.json方法允许您无条件地挂载第三方块,这意味着在上述限制的情况下,该块将相对于目标(锚点)块的所有实例插入。
在块的block.json文件中,包含该blockHooks属性。此属性采用一个对象,其中键 ( string) 是要挂载的块的名称,值 ( string) 指定其位置。可能的位置有:
- before– 在目标块之前注入。
- after– 在目标块之后注入。
- firstChild– 在目标容器块的第一个内部块之前注入。
- lastChild– 在目标容器块的最后一个内部块之后注入。
{
    blockHooks: {
        'core/verse': 'before'
        'core/spacer': 'after',
        'core/column': 'firstChild',
        'core/comment-template': 'lastChild',
    }
}在上面的示例中,该块将插入到出现在未修改的模板、模板部分或样板中的每个 Verse 块之前。它还将被插入到每个 Spacer 块之后,等等。
当使用 firstChild 或 lastChild 的block.json方法时,标题为“插件”的设置侧边栏面板将被添加到编辑器中的目标块中。这允许用户打开和关闭挂钩块。
下面是一个链接到“评论模板”块中的 lastChild 位置的“赞”按钮块的示例。

hooked_block_types
hooked_block_types过滤器提供了更大的灵活性。它允许您像 block.json 方法一样无条件地挂钩任何动态块,或者根据目标(锚点)块所在的模板、模板部分或样板有条件地挂钩。
过滤器的回调函数接受四个参数:
- $hooked_blocks(array) – 钩子块的数组。
- $position(string) – 挂载的块的相对位置:- before、- after、- first_child、 或- last_child。
- $anchor_block(字符串) – 锚块的名称。
- $context(WP_Block_Template|array) – 锚块所属的块模板、模板部分或样板。
下面是一些使用Like 按钮块插件 ( ockham/like-button) 的示例,旨在演示第三方块中的区块钩子功能。该样板示例确实需要2024主题。
function example_block_hooks( $hooked_blocks, $position, $anchor_block, $context ) {
	// Template/Template Part hooks.
	if ( $context instanceof WP_Block_Template ) {
		
		// Hooks the "Like" button block before the Post Title in the Single template.
		if ( 
			'core/post-title' === $anchor_block &&
			'before' === $position &&
			'single' === $context->slug
		) {
			$hooked_blocks[] = 'ockham/like-button';
		}
		// Hooks the Login/Logout link block after the Navigation block if the context of the template part is a header.
		if ( 
			'core/group' === $anchor_block &&
			'last_child' === $position &&
			'header' === $context->area
		) {
			$hooked_blocks[] = 'core/loginout';
		}
	}
	// Pattern hooks.
	if ( is_array( $context ) && isset( $context['slug'] ) ) {
		
		// Hooks into the Post Meta pattern in the Twenty Twenty-Four theme.
		if ( 
			'core/post-terms' === $anchor_block && 
			'after' === $position && 
			'twentytwentyfour/post-meta' === $context['slug']
		) {
			$hooked_blocks[] = 'ockham/like-button';
		}
	}
	return $hooked_blocks;
}
add_filter( 'hooked_block_types', 'example_block_hooks', 10, 4 );值得注意的是,$context 将是 WP_Block_Template 模板和模板部件的 object 类型以及样板的 array 类型。如果要使用此参数有条件地插入块,请确保在应用挂钩块之前检查参数类型。
您还会注意到,您只能指定正在挂钩的块的名称。无法设置挂钩块的属性,因此仅插入块的默认实例。区块钩子的未来改进可能会解决此限制和其他限制,为开发人员扩展块主题提供可靠的方法。
有关当前正在开发哪些附加功能的更多信息,请继续关注区块钩子改进的跟踪问题。





