WordPress 5.4 并非很久之前发布,除了其他改进和错误修复之外,它还引入了一项名为“区块变体”的功能。我最近在一个项目中使用了它,对该功能的智能程度感到惊喜。实际上,我认为它并没有得到应有的关注,因此我决定撰写本文。
什么是区块变体?
区块变体允许开发人员定义现有区块的实例。您将在下面看到的示例是一个引用区块。也许您的网站有三种不同的方式来显示引用。可以为每种方式创建一个区块变体,以便它们都以不同的方式进行样式设置。这听起来非常类似于区块样式,但变体的概念比这更进一步,正如我们将看到的。
区块变体与区块样式有何不同?
合理的问题。区块变体在插入器中显示为具有唯一名称(以及可选的)图标的单独区块,并且可以具有预填充的自定义属性和内部区块。
区块样式旨在更改区块的外观。实际上,区块样式是使用帖子编辑器中的区块选项向区块添加自定义类的一种花哨方法。
当您考虑如何在帖子编辑器中使用每个选项时,差异就很明显了。假设我们注册了一个名为“花哨引用”的新区块样式。我们通过扩展核心“引用”区块来做到这一点,例如来自 区块编辑器手册 的此示例
wp.blocks.registerBlockStyle(
'core/quote',
{
name: 'fancy-quote',
label: 'Fancy Quote'
},
);
这会将 .is-style-fancy-quote
类添加到帖子编辑器中引用区块设置中。

尽管它听起来像是会做相同的事情(从技术上讲它可以做到),但区块变体可用于预填充自定义属性(包括自定义类)和内部区块。它们实际上是作为单独的区块注册的。
让我们更仔细地看看 API 和区块变体可以做什么。
创建区块变体
注册区块变体的 API 与我们刚刚看到的区块样式非常相似
wp.blocks.registerBlockVariation(
'core/quote',
{
name: 'fancy-quote',
title: 'Fancy Quote',
},
);
registerBlockVariation
函数接受区块的名称(在我们的例子中是 core/quote)和一个描述变体的对象(或对象数组)。
上面的代码默认情况下不会做太多事情,但它确实将“花哨引用”添加到可用区块列表中。

要充分利用变体,我们需要在描述它的对象中提供更多详细信息。该列表在 Make WordPress 文章 中有介绍,但我会在这里分享它并提供其他注释。
name
– 变体的唯一且机器可读的名称。根据 Github 和 Make 文章上的示例,可以假设最佳实践是使用 kebab-case 来命名变体。title
– 人类可读的变体标题。这是插入器图标下显示的内容。description
– 详细的变体描述。也显示在插入器中。如果为空,将使用默认的区块描述。(可选)icon
– 变体的图标。可以是 Dashicons slug、SVG 或对象。遵循与registerBlockType
中相同的声明模式。(可选)isDefault
– 指示当前变体是否为默认变体。默认为false
。在我们的示例中,如果将其设置为true
,则花哨引用区块将是插入器中唯一可用的引用区块。(可选)attributes
– 覆盖区块属性的值。这些是特定于区块的。例如,您可以为标题区块设置level
或为间隔符设置height
。innerBlocks
– 嵌套区块的初始配置。仅适用于首先允许内部区块的区块,例如列、封面或组。我们将在其中一个示例中介绍这一点。(可选)example
– 示例为区块预览提供结构化数据。您可以将其设置为undefined
以禁用为区块类型显示的预览。这与registerBlockType
中的示例字段相同。(可选)有关此参数,请参阅 更多信息。scope
– 变体适用的范围列表。如果未提供,则假定所有可用范围。可用选项包括block
和inserter
。我们将在其中一个示例中详细介绍。
你们中的许多人可能想知道为什么我们需要这种额外的抽象层。我将尝试通过一些用例(来自我最近的一个项目)来回答这个问题。
用例:具有不同宽度的按钮
假设您的设计系统有两种类型的按钮:填充和轮廓。

幸运的是,这些是 WordPress 中按钮的默认样式。无需注册任何新样式或修改编辑器。您只需为每种样式编写一些 CSS 即可。生活很美好,每个人都很快乐。
但是,您再次查看设计规范后发现有一些变化。按钮有三种宽度:常规、宽和全宽。

该死!您有点沮丧,因为您现在有两个选择
- 为新的按钮尺寸编写两个额外的类(例如,
.is-wide
和.is-full
),然后教客户使用编辑器中的高级面板添加这些类,并编写一本手册,说明每个类的作用。或者…… - 注册四个(!)新的样式,它们位于区块选项中:填充宽、填充全宽、轮廓宽和轮廓全宽。
这两个选项都不是很优雅。(顺便说一句,“填充全宽”到底是什么?真是一个不幸的词语!)
还有两个选项我没有列出
- 过滤按钮区块并向其添加自定义宽度控件
- 从头开始构建自定义区块。
对于这样一项简单的任务来说,这些显然感觉像是繁重的工作。
输入区块变体!通过添加仅两个变体,全宽和宽,我们可以保持简洁和简单
wp.blocks.registerBlockVariation(
'core/buttons',
[
{
name: 'wide',
title: 'Wide Buttons',
attributes: {
className: 'is-wide'
},
},
{
name: 'full',
title: 'Full Buttons',
attributes: {
className: 'is-full'
},
}
]
);
这与向按钮区块添加自定义类相同,但它以一种整洁且优雅的方式直接从区块插入器中添加到帖子中

生活很美好,每个人都再次快乐!**我们从这个例子中学到了什么?**
- 它表明区块变体并非旨在取代区块样式。实际上,即使变体只是向区块添加一个类,它们也可以很好地协同工作。
- 它演示了如何在单个声明中注册多个变体。
用例:重复的列布局
假设您是一位设计师,并且有一个包含案例研究的投资组合网站。每个案例研究都有一个介绍部分,其中包含项目名称、客户信息以及您在项目中的角色描述。它可能如下所示

问题在于,每次创建新的投资组合案例研究时,构建布局的这一部分都有些乏味——尤其是在客户和我的角色标题永远不会改变的情况下。您只需要编辑主标题和两个段落。
使用区块变体,您可以创建一个核心列区块的变体,称为项目简介,其中将预定义列和内部区块。此示例稍微复杂一些,因此我们将逐步构建它。
让我们从注册变体开始
wp.blocks.registerBlockVariation(
'core/columns', {
name: 'project-intro',
title: 'Project Intro',
scope: ['inserter'],
innerBlocks: [
['core/column'],
['core/column'],
['core/column'],
],
}
);
我们在这个例子中比第一个例子更进一步,所以为什么不从WordPress中内置的Dashicons库添加一个自定义的投资组合图标呢?我们使用icon
属性来实现。
wp.blocks.registerBlockVariation(
'core/columns', {
name: 'project-intro',
title: 'Project Intro',
icon: 'portfolio',
scope: ['inserter'],
innerBlocks: [
['core/column'],
['core/column'],
['core/column'],
],
}
);
这将使区块在区块菜单中以我们的图标显示。

接下来重要的事情发生在添加内部区块的地方。
wp.blocks.registerBlockVariation(
'core/columns', {
name: 'project-intro',
title: 'Project Intro',
icon: 'portfolio',
scope: ['inserter'],
innerBlocks: [
['core/column'],
['core/column'],
['core/column'],
],
}
);
但这只会给我们三个空的列。让我们在每个列中添加起始内容和内部区块。我们可以使用与在InnerBlocks
组件中声明区块模板相同的模式。我们可以添加一个包含区块属性的对象作为数组中的第二个元素,以及一个包含内部区块的数组作为第三个元素。
第一列将如下所示
['core/column', {}, [
['core/heading', { level: 2, placeholder: 'Project Title'} ],
]]
…完整的区块变体如下所示
wp.blocks.registerBlockVariation (
'core/columns', {
name: 'project-intro',
title: 'Project Intro',
icon: 'portfolio',
scope: ['inserter'],
innerBlocks: [
['core/column', {}, [
['core/heading', { level: 2, placeholder: 'Project Title' }],
]],
['core/column', {}, [
['core/heading', { level: 3, content: 'Client' }],
['core/paragraph', { placeholder: 'Enter client info' }],
]],
['core/column', {}, [
['core/heading', { level: 3, content: 'My Role' }],
['core/paragraph', { placeholder: 'Describe your role' }],
]],
],
}
);
酷,现在我们只需点击一下即可插入整个区块。好吧,是几次点击,但仍然比不使用变体快。
那么我们从这个例子中学到了什么?
- 并演示如何在变体中使用内部区块。
- 它展示了如何为变体定义自定义图标。
用例:四列布局
您已经知道列是一种默认的区块类型,并且有几种不同类型的列选项。四列布局不是其中之一,因此我们可以构建它。但这同时也引入了一个新概念:在区块变体的上下文中进行作用域。
一些核心区块,例如列,已经开箱即用地提供了变体。您可以在页面上插入区块之后选择其中一个。

假设您在网站上使用四列布局的频率与使用两列布局的频率一样高。这很不幸,因为没有快捷按钮可以创建四列布局。创建它有点烦人,因为在插入区块后需要额外点击才能到达列控件。

那么,您可以做些什么来改进此工作流程呢?没错,您可以添加一个区块变体来创建四列布局。与之前的示例相比,这次唯一的区别是,将此变体包含在区块占位符中,与所有其他列布局并排放置,更有意义。
这正是scope
选项的作用。如果您将其设置为[block]
,则变体不会出现在区块插入器中,而是在插入区块后出现在变体中。
wp.blocks.registerBlockVariation(
'core/columns', {
name: 'four-columns',
title: 'Four columns; equal split',
icon: <svg ... />,
scope: ['block'], // Highlight
innerBlocks: [
['core/column'],
['core/column'],
['core/column'],
['core/column'],
],
}
);

是不是很不错?!
我省略了图标的完整 SVG 代码,但如果您需要,它可以获取。
总结一下scope
:如果未声明,则变体将出现在区块插入器和区块占位符中——特别是对于支持区块作用域变体的区块。
如果我们要从上面的示例中删除作用域参数,则变体将如下所示出现在插入器中

那么我们从这个例子中学到了什么?
- 它解释了区块和插入器作用域在变体中的区别。
- 我们学习了如何使用 SVG 作为变体图标。
就是这样!
如您所见,区块变体对于构建许多事物非常强大,从不同类型的按钮到完整的页面布局。
我想以快速回顾一下用于区块自定义的不同 API 以及何时使用它们来结束本文。
- 如果需要更改区块的外观,并且添加 CSS 类足以实现此目的,则使用区块样式。
- 如果需要为区块指定默认属性和/或向其中添加内部区块,则使用区块变体。
- 如果这还不够,并且需要更改区块的标记,则可能需要考虑过滤区块或从头创建一个新的区块。
如果您有机会试用区块变体,请在评论中告诉我您对它们的看法!
太棒了!这非常有帮助。非常感谢!
如果Gutenberg允许您选择多种样式,第一个按钮示例将非常容易。实现起来也非常容易。
是的!正如上面所述,确实非常有用。但将这些变体写入一个新的插件中非常重要。这样,在切换主题时就不必担心了。非常感谢您提供的关于区块变体的见解。WordPress和Gutenberg将长期共存。
感谢您的文章。我们将代码放在哪里才能使其生效?
有没有办法将其添加到functions.php中?是否有简单的插件示例?
谢谢。
很棒,但我没有找到如何阻止嵌套区块,因为在创建新区块时可以使用templateLock: 'all'。
好文章!
您是否注意到您的区块变体没有显示在斜杠插入器中?好奇是不是只有我这样……我在此处发布了一个问题:https://github.com/WordPress/gutenberg/issues/22542
我体验到了使用原生区块与 ACF 区块的缺点。如果您决定稍后在模板中全局修改某个区块的
className
,这并不像在模板中更改它那样简单。WordPress不会自动将新的类名应用于过去条目中已建立的区块。您希望只需更新条目,WordPress也会更新类名值,但事实并非如此。我发现这非常有帮助。
您是如何在这个JavaScript区块中直接实现SVG代码的?
也许我误解了什么,但带有不同尺寸按钮的第一个示例不应该是简单区块样式变体的完美示例吗?无需向客户解释添加自定义类名,因为只需点击按钮即可选择备用样式的UI。让客户熟悉此功能应该不难,一旦他们了解了它,它就是一个简单的操作。
我认为,如果变体只是添加了不同的样式,它应该是一个简单的区块样式变体,只有在添加功能差异时,它才能成为区块变体。
我正在寻找WordPress中的区块样式,然后来到了这里。无论如何,很高兴了解此功能。深入且写得很好。我可能会在我的新WordPress安装中尝试此功能!
谢谢!我写了一篇关于FSE/自定义分类法的文章,其中引用了另一篇文章,最后引用了这篇文章!哈哈。这就像与凯文·贝肯隔了六度。
https://wordpresscenter.net/2022/10/11/wordpress-custom-taxonomies-display-in-block-editor/
干杯!