248 lines
11 KiB
Markdown
248 lines
11 KiB
Markdown
|
|
# 区块变体
|
|||
|
|
|
|||
|
|
区块变体API允许您为区块定义多个版本(变体)。区块变体通过一组初始属性或内部区块与原始区块区分开来。当您将区块变体插入编辑器时,这些属性和/或内部区块会被应用。
|
|||
|
|
|
|||
|
|
变体是在不从头构建全新区块的情况下,创建现有区块迭代版本的绝佳方式。
|
|||
|
|
|
|||
|
|
为了更好地理解此API,请以嵌入区块为例。该区块包含多种可嵌入内容类型(WordPress、YouTube等)的众多变体。每个嵌入区块变体共享相同的底层功能,如编辑、保存等。除了名称和描述信息外,主要区别在于`providerNameSlug`属性。以下是嵌入区块变体的简化示例。完整规范请查看[源代码](https://github.com/WordPress/gutenberg/blob/trunk/packages/block-library/src/embed/variations.js)。
|
|||
|
|
|
|||
|
|
```js
|
|||
|
|
variations: [
|
|||
|
|
{
|
|||
|
|
name: 'wordpress',
|
|||
|
|
title: 'WordPress',
|
|||
|
|
description: __( '嵌入WordPress文章。' ),
|
|||
|
|
attributes: { providerNameSlug: 'wordpress' },
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
name: 'youtube',
|
|||
|
|
title: 'YouTube',
|
|||
|
|
description: __( '嵌入YouTube视频。' ),
|
|||
|
|
attributes: { providerNameSlug: 'youtube' },
|
|||
|
|
},
|
|||
|
|
],
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 定义区块变体
|
|||
|
|
|
|||
|
|
区块变体通过包含以下字段的对象定义:
|
|||
|
|
|
|||
|
|
- `name`(类型`string`)– 唯一且机器可读的名称
|
|||
|
|
- `title`(可选,类型`string`)– 人类可读的变体标题
|
|||
|
|
- `description`(可选,类型`string`)– 人类可读的变体描述
|
|||
|
|
- `category`(可选,类型`string`)- 在搜索界面中用于按分类排列区块类型的分类标识
|
|||
|
|
- `keywords`(可选,类型`string[]`)- 帮助用户在搜索时发现变体的术语数组(可翻译)
|
|||
|
|
- `icon`(可选,类型`string` | `Object`)– 帮助可视化变体的图标,可与区块类型保持相同样式
|
|||
|
|
- `attributes`(可选,类型`Object`)– 覆盖区块属性的值
|
|||
|
|
- `innerBlocks`(可选,类型`Array[]`)– 嵌套区块的初始配置
|
|||
|
|
- `example`(可选,类型`Object`)– 为区块预览提供结构化数据。设置为`undefined`可禁用预览。详见[区块注册API](/docs/reference-guides/block-api/block-registration.md#example-optional)
|
|||
|
|
- `scope`(可选,类型`WPBlockVariationScope[]`)- 默认为`block`和`inserter`。变体适用的作用域列表,可用选项包括:
|
|||
|
|
- `block` - 被区块用于筛选特定区块变体。`Columns`和`Query`区块包含此类变体,这些变体会传递给[实验性BlockVariationPicker](https://github.com/WordPress/gutenberg/blob/HEAD/packages/block-editor/src/components/block-variation-picker/README.md)组件,该组件负责显示变体并允许用户选择
|
|||
|
|
- `inserter` - 在插入器中显示区块变体
|
|||
|
|
- `transform` - 在变体转换组件中显示区块变体
|
|||
|
|
- `isDefault`(可选,类型`boolean`)– 默认为`false`。指示当前变体是否为默认变体(详见下文)
|
|||
|
|
- `isActive`(可选,类型`Function|string[]`)- 用于确定选中区块时变体是否处于活动状态的函数或区块属性数组。该函数接受`blockAttributes`和`variationAttributes`参数(详见下文)
|
|||
|
|
|
|||
|
|
<div class="callout callout-info">
|
|||
|
|
从技术上讲,您可以创建没有唯一<code>name</code>的区块变体,但<strong>不推荐</strong>这样做。唯一的<code>name</code>允许编辑器区分您的变体与其他可能存在的变体,还允许在需要时注销您的变体,并对<code>isDefault</code>设置产生影响(详见下文)。
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
## 创建区块变体
|
|||
|
|
|
|||
|
|
在区块注册过程中,可通过为`variations`键提供规范的变体对象数组来声明区块变体,如上例所示。更多详细信息请参阅[区块注册API](/docs/reference-guide/block-api/block-registration.md)。
|
|||
|
|
|
|||
|
|
若要为现有区块(如核心区块)创建变体,请使用`wp.blocks.registerBlockVariation()`。该函数接受区块名称和定义变体的对象。
|
|||
|
|
|
|||
|
|
```js
|
|||
|
|
wp.blocks.registerBlockVariation( 'core/embed', {
|
|||
|
|
name: 'custom-embed',
|
|||
|
|
attributes: { providerNameSlug: 'custom' },
|
|||
|
|
} );
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 通过PHP注册区块变体
|
|||
|
|
|
|||
|
|
区块变体也可使用`get_block_type_variations`过滤器钩子在PHP中注册。当需要基于已注册的文章类型、分类法或其他WordPress数据动态生成变体时,这种方法特别有用。
|
|||
|
|
|
|||
|
|
以下是为`core/image`区块注册自定义变体的示例:
|
|||
|
|
|
|||
|
|
```php
|
|||
|
|
function my_custom_image_variation( $variations, $block_type ) {
|
|||
|
|
// 仅修改图片区块的变体
|
|||
|
|
if ( 'core/image' !== $block_type->name ) {
|
|||
|
|
return $variations;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 添加自定义变体
|
|||
|
|
$variations[] = array(
|
|||
|
|
'name' => 'wide-image',
|
|||
|
|
'title' => __( '宽幅图片', 'textdomain' ),
|
|||
|
|
'description' => __( '宽幅图片', 'textdomain' ),
|
|||
|
|
'scope' => array( 'inserter' ),
|
|||
|
|
'isDefault' => false,
|
|||
|
|
'attributes' => array(
|
|||
|
|
'align' => 'wide', // 标识为自定义链接类型
|
|||
|
|
),
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
return $variations;
|
|||
|
|
}
|
|||
|
|
add_filter( 'get_block_type_variations', 'my_custom_image_variation', 10, 2 );
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
当请求区块类型的变体时会调用`get_block_type_variations`过滤器。它接收两个参数:
|
|||
|
|
- `$variations`:当前已注册的区块类型变体数组
|
|||
|
|
- `$block_type`:完整的区块类型对象
|
|||
|
|
|
|||
|
|
注意:通过PHP注册的变体将与使用`registerBlockVariation()`通过JavaScript注册的任何变体合并。
|
|||
|
|
|
|||
|
|
<div class="callout callout-info">查看<a href="https://developer.wordpress.org/news/2024/03/how-to-register-block-variations-with-php/">如何使用PHP注册区块变体</a>博客文章获取更多信息</div>
|
|||
|
|
|
|||
|
|
## 移除区块变体
|
|||
|
|
|
|||
|
|
区块变体也可以轻松移除。为此,请使用`wp.blocks.unregisterBlockVariation()`。该函数接受区块名称和需要注销的变体`name`。
|
|||
|
|
|
|||
|
|
```js
|
|||
|
|
wp.blocks.unregisterBlockVariation( 'core/embed', 'youtube' );
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 区块变体与区块样式
|
|||
|
|
|
|||
|
|
区块样式与区块变体的主要区别在于:区块样式仅向区块应用CSS类,从而能以替代方式进行样式设计。更多详细信息请参阅[区块样式API](/docs/reference-guides/block-api/block-styles.md)。
|
|||
|
|
|
|||
|
|
若要设置初始属性或内部区块,则属于区块变体范畴。在定义区块变体时,也可以通过`className`属性覆盖默认区块样式。
|
|||
|
|
|
|||
|
|
```js
|
|||
|
|
variations: [
|
|||
|
|
{
|
|||
|
|
name: 'blue',
|
|||
|
|
title: __( '蓝色引用' ),
|
|||
|
|
isDefault: true,
|
|||
|
|
attributes: {
|
|||
|
|
color: 'blue',
|
|||
|
|
className: 'is-style-blue-quote'
|
|||
|
|
},
|
|||
|
|
icon: 'format-quote',
|
|||
|
|
isActive: ( blockAttributes, variationAttributes ) =>
|
|||
|
|
blockAttributes.color === variationAttributes.color
|
|||
|
|
},
|
|||
|
|
],
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 使用`isDefault`标志
|
|||
|
|
|
|||
|
|
默认情况下,所有变体都会在插入器中与原始区块类型项共同显示。但为列出的任何变体设置`isDefault`标志将覆盖插入器中的常规区块类型。这是根据特定需求定制编辑器体验的强大工具。
|
|||
|
|
|
|||
|
|
例如,若希望媒体与文本区块默认在右侧显示图像,可创建如下变体:
|
|||
|
|
|
|||
|
|
```js
|
|||
|
|
wp.blocks.registerBlockVariation( 'core/media-text', {
|
|||
|
|
name: 'media-text-media-right',
|
|||
|
|
title: __( '媒体与文本' ),
|
|||
|
|
isDefault: true,
|
|||
|
|
attributes: {
|
|||
|
|
mediaPosition: 'right',
|
|||
|
|
},
|
|||
|
|
} );
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 使用 `isDefault` 的注意事项
|
|||
|
|
|
|||
|
|
虽然 `isDefault` 在覆盖没有现有变体的区块时效果很好,但当存在其他变体时,您可能会遇到问题。
|
|||
|
|
|
|||
|
|
如果同一区块的另一个变体使用了 `isDefault`,您的变体不一定会成为默认变体。编辑器会尊重第一个注册的带有 `isDefault` 的变体,这可能不是您的变体。
|
|||
|
|
|
|||
|
|
解决方案是在注册带有 `isDefault` 的变体之前,先取消注册其他变体。这一注意事项进一步强调了始终为变体提供唯一 `name` 的建议。否则,该变体将无法被取消注册。
|
|||
|
|
|
|||
|
|
## 使用 `isActive`
|
|||
|
|
|
|||
|
|
虽然 `isActive` 属性是可选的,但建议使用它。区块编辑器使用此 API 来检查哪个变体处于活动状态,并在编辑器中选择该变体的实例时显示正确的变体标题、图标和描述。
|
|||
|
|
|
|||
|
|
如果未设置 `isActive`,编辑器将无法区分原始区块的实例和您的变体,因此将显示原始区块的信息。
|
|||
|
|
|
|||
|
|
该属性可以设置为字符串数组(`string[]`)或函数。建议尽可能使用字符串数组版本。
|
|||
|
|
|
|||
|
|
`string[]` 版本用于声明应将区块实例的哪些属性与给定变体的属性进行比较。每个属性都将被检查,如果所有属性都匹配,则该变体将处于活动状态。
|
|||
|
|
|
|||
|
|
例如,在核心的 Embed 区块中,`providerNameSlug` 属性用于确定嵌入提供程序(例如 “youtube” 或 “twitter”)。变体可以这样声明:
|
|||
|
|
|
|||
|
|
```js
|
|||
|
|
const variations = [
|
|||
|
|
{
|
|||
|
|
name: 'twitter',
|
|||
|
|
title: 'Twitter',
|
|||
|
|
icon: embedTwitterIcon,
|
|||
|
|
keywords: [ 'tweet', __( 'social' ) ],
|
|||
|
|
description: __( '嵌入推文。' ),
|
|||
|
|
patterns: [ /^https?:\/\/(www\.)?twitter\.com\/.+/i ],
|
|||
|
|
attributes: { providerNameSlug: 'twitter', responsive: true },
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
name: 'youtube',
|
|||
|
|
title: 'YouTube',
|
|||
|
|
icon: embedYouTubeIcon,
|
|||
|
|
keywords: [ __( '音乐' ), __( '视频' ) ],
|
|||
|
|
description: __( '嵌入 YouTube 视频。' ),
|
|||
|
|
patterns: [
|
|||
|
|
/^https?:\/\/((m|www)\.)?youtube\.com\/.+/i,
|
|||
|
|
/^https?:\/\/youtu\.be\/.+/i,
|
|||
|
|
],
|
|||
|
|
attributes: { providerNameSlug: 'youtube', responsive: true },
|
|||
|
|
},
|
|||
|
|
// ...
|
|||
|
|
];
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
那么 `isActive` 属性将如下所示:
|
|||
|
|
|
|||
|
|
```js
|
|||
|
|
isActive: [ 'providerNameSlug' ];
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
这将导致区块实例的 `providerNameSlug` 值与变体声明中的值(上述代码片段中的值)进行比较,以确定哪个嵌入变体处于活动状态。
|
|||
|
|
|
|||
|
|
自 WordPress `6.6.0` 起,还支持嵌套对象路径。例如,假设一个区块变体具有 `query` 对象作为属性。可以仅基于该对象的 `postType` 属性(同时忽略其所有其他属性)来确定变体是否处于活动状态:
|
|||
|
|
|
|||
|
|
```js
|
|||
|
|
isActive: [ 'query.postType' ];
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
该属性的函数版本接受区块实例的 `blockAttributes` 作为第一个参数,以及为变体声明的 `variationAttributes` 作为第二个参数。可以通过比较这些参数来确定变体是否处于活动状态,并返回 `true` 或 `false`(表示此变体是否对此区块实例处于活动状态)。
|
|||
|
|
|
|||
|
|
以嵌入区块的相同示例为例,函数版本将如下所示:
|
|||
|
|
|
|||
|
|
```js
|
|||
|
|
isActive: ( blockAttributes, variationAttributes ) =>
|
|||
|
|
blockAttributes.providerNameSlug === variationAttributes.providerNameSlug,
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### `isActive` 匹配的特定性
|
|||
|
|
|
|||
|
|
*注意:自 WordPress `6.6.0` 起改进了处理方式。*
|
|||
|
|
|
|||
|
|
如果有多个变体的 `isActive` 检查匹配给定的区块实例,并且所有变体都是字符串数组,则将选择*特定性*最高的变体。考虑以下示例:
|
|||
|
|
|
|||
|
|
```js
|
|||
|
|
wp.blocks.registerBlockVariation( 'core/paragraph', {
|
|||
|
|
name: 'paragraph-red',
|
|||
|
|
title: '红色段落',
|
|||
|
|
attributes: {
|
|||
|
|
textColor: 'vivid-red',
|
|||
|
|
},
|
|||
|
|
isActive: [ 'textColor' ],
|
|||
|
|
} );
|
|||
|
|
|
|||
|
|
wp.blocks.registerBlockVariation( 'core/paragraph', {
|
|||
|
|
name: 'paragraph-red-grey',
|
|||
|
|
title: '红/灰段落',
|
|||
|
|
attributes: {
|
|||
|
|
textColor: 'vivid-red',
|
|||
|
|
backgroundColor: 'cyan-bluish-gray',
|
|||
|
|
},
|
|||
|
|
isActive: [ 'textColor', 'backgroundColor' ],
|
|||
|
|
} );
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
如果某个区块实例具有属性 `textColor: vivid-red` 和 `backgroundColor: cyan-bluish-gray`,则两个变体的 `isActive` 条件都将匹配该区块实例。在这种情况下,将确定*特定性*更高的匹配为活动变体,其中特定性计算为每个 `isActive` 数组的长度。这意味着 `红/灰段落` 将显示为活动变体。
|
|||
|
|
|
|||
|
|
请注意,如果匹配变体的 `isActive` 属性是函数而不是 `string[]`,则无法确定其特定性。在这种情况下,第一个匹配的变体将被确定为活动变体。因此,通常建议为 `isActive` 属性使用 `string[]` 而不是 `function`。
|