first commit
This commit is contained in:
22
reference-guides/block-api/README.md
Normal file
22
reference-guides/block-api/README.md
Normal file
@@ -0,0 +1,22 @@
|
||||
# 区块 API 参考
|
||||
|
||||
区块是编辑器的基本组成单元,也是插件和主题注册自身功能、扩展编辑器能力的主要方式。
|
||||
|
||||
以下章节将引导您了解现有的区块 API:
|
||||
|
||||
- [注释](/docs/reference-guides/block-api/block-annotations.md)
|
||||
- [API 版本](/docs/reference-guides/block-api/block-api-versions.md)
|
||||
- [属性](/docs/reference-guides/block-api/block-attributes.md)
|
||||
- [绑定](/docs/reference-guides/block-api/block-bindings.md)
|
||||
- [上下文](/docs/reference-guides/block-api/block-context.md)
|
||||
- [弃用说明](/docs/reference-guides/block-api/block-deprecation.md)
|
||||
- [编辑与保存](/docs/reference-guides/block-api/block-edit-save.md)
|
||||
- [block.json 中的元数据](/docs/reference-guides/block-api/block-metadata.md)
|
||||
- [模式](/docs/reference-guides/block-api/block-patterns.md)
|
||||
- [注册](/docs/reference-guides/block-api/block-registration.md)
|
||||
- [选择器](/docs/reference-guides/block-api/block-selectors.md)
|
||||
- [样式](/docs/reference-guides/block-api/block-styles.md)
|
||||
- [支持特性](/docs/reference-guides/block-api/block-supports.md)
|
||||
- [转换功能](/docs/reference-guides/block-api/block-transforms.md)
|
||||
- [模板](/docs/reference-guides/block-api/block-templates.md)
|
||||
- [变体](/docs/reference-guides/block-api/block-variations.md)
|
||||
61
reference-guides/block-api/block-annotations.md
Normal file
61
reference-guides/block-api/block-annotations.md
Normal file
@@ -0,0 +1,61 @@
|
||||
# 标注功能
|
||||
|
||||
<div class="callout callout-alert">
|
||||
<strong>注意:</strong> 此 API 为实验性功能,这意味着在未来的任何版本中可能会发生不向后兼容的变更或被移除。
|
||||
</div>
|
||||
|
||||
标注是一种高亮区块编辑器中创建的文章特定片段的方式。典型应用包括文本批注与拼写检查,两者均可通过标注 API 对文本片段进行标记。
|
||||
|
||||
## API
|
||||
|
||||
要直观了解 API,最简便的方式是创建一个至少包含 200 个无格式字符的区块,并在控制台中执行以下代码:
|
||||
|
||||
```js
|
||||
wp.data.dispatch( 'core/annotations' ).addAnnotation( {
|
||||
source: 'my-annotations-plugin',
|
||||
blockClientId: wp.data.select( 'core/block-editor' ).getBlockOrder()[ 0 ],
|
||||
richTextIdentifier: 'content',
|
||||
range: {
|
||||
start: 50,
|
||||
end: 100,
|
||||
},
|
||||
} );
|
||||
```
|
||||
|
||||
范围起始点与结束点的计算应仅基于相应 `RichText` 的纯文本内容。例如在以下 HTML 中,位置 0 将指向大写字母 S 之前的位置:
|
||||
|
||||
```html
|
||||
<strong>加粗文本</strong>
|
||||
```
|
||||
|
||||
为帮助确定正确位置,可使用 `wp.richText.create` 方法。该方法会将 HTML 片段拆分为文本内容与格式标记。
|
||||
|
||||
所有可用属性均可在 `addAnnotation` 操作的 API 文档中查阅。
|
||||
|
||||
`richTextIdentifier` 属性用于指定标注所应用的富文本实例标识符。由于区块可能包含多个用于管理不同属性数据的富文本实例,必须传入此参数才能确保在正确的实例中高亮文本。
|
||||
|
||||
例如段落区块仅包含单个标识符为 `content` 的富文本实例。引述区块类型则拥有 2 个富文本实例,若需在引注部分高亮文本,添加标注时需将 `citation` 作为 `richTextIdentifier` 传入;若需定位引述内容,则需使用标识符 `value`。具体标识符请参考区块类型的源代码。
|
||||
|
||||
## 区块标注
|
||||
|
||||
也可对完整区块进行标注。此时只需提供值为 `block` 的 `selector` 属性。默认的 `selector` 为 `range`,适用于文本标注场景。
|
||||
|
||||
```js
|
||||
wp.data.dispatch( 'core/annotations' ).addAnnotation( {
|
||||
source: 'my-annotations-plugin',
|
||||
blockClientId: wp.data.select( 'core/block-editor' ).getBlockOrder()[ 0 ],
|
||||
selector: 'block',
|
||||
} );
|
||||
```
|
||||
|
||||
此操作不会自动提供样式支持,因此需要额外添加 CSS 以确保标注可见:
|
||||
|
||||
```css
|
||||
.is-annotated-by-my-annotations-plugin {
|
||||
outline: 1px solid black;
|
||||
}
|
||||
```
|
||||
|
||||
## 文本标注
|
||||
|
||||
文本标注通过 `start` 与 `end` 属性进行控制。由于简单的起止位置属性无法直接适用于 HTML 环境,这两个属性被设计为 `rich-text` 内部结构中的偏移量。为简化理解,可将其视为去除所有 HTML 标记后,在纯文本环境中计算的标注起止位置。
|
||||
16
reference-guides/block-api/block-api-versions.md
Normal file
16
reference-guides/block-api/block-api-versions.md
Normal file
@@ -0,0 +1,16 @@
|
||||
# API 版本说明
|
||||
|
||||
本文档记录了不同 API 版本之间的变更内容。
|
||||
|
||||
## 版本 3(适用于 WordPress 6.3 及以上版本)
|
||||
- 当所有已注册区块均采用区块 API 第 3 版或更高版本时,文章编辑器将采用 iframe 内嵌模式。支持第 3 版意味着区块应能在 iframe 内正常工作,但若存在不支持第 3 版的区块,该区块仍可能在 iframe 外渲染。
|
||||
- 请参阅[本文](https://make.wordpress.org/core/2021/06/29/blocks-in-an-iframed-template-editor/)获取迁移指南,了解如何将 API 版本升级至第 3 版并确保在 iframe 编辑器中正常运行。
|
||||
|
||||
## 版本 2(适用于 WordPress 5.6 及以上版本)
|
||||
|
||||
- 区块开发者必须使用 `useBlockProps()` 钩子函数来渲染区块 `edit` 实现的包装元素。
|
||||
- 在处理 `save` 功能时,生成的类名和样式不再自动添加到静态区块的保存标记中。如需保留这些样式,区块开发者必须显式调用 `useBlockProps.save()` 并将其添加到区块包装器中。
|
||||
|
||||
## 版本 1
|
||||
|
||||
初始版本。
|
||||
495
reference-guides/block-api/block-attributes.md
Normal file
495
reference-guides/block-api/block-attributes.md
Normal file
@@ -0,0 +1,495 @@
|
||||
# 属性
|
||||
|
||||
区块属性提供了关于区块存储数据的信息。例如:富文本内容、图片URL列表、背景色或按钮标题。
|
||||
|
||||
一个区块可以包含任意数量的属性,这些属性通过`attributes`字段指定——该对象中的每个键都是属性名称,值则是属性定义。
|
||||
|
||||
属性定义至少包含`type`或`enum`之一,也可能包含其他字段。
|
||||
|
||||
*示例*:定义三个属性(`url`、`title`和`size`)的属性对象。
|
||||
|
||||
```js
|
||||
{
|
||||
url: {
|
||||
type: 'string',
|
||||
source: 'attribute',
|
||||
selector: 'img',
|
||||
attribute: 'src',
|
||||
},
|
||||
title: {
|
||||
type: 'string',
|
||||
},
|
||||
size: {
|
||||
enum: [ 'large', 'small' ],
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
当区块被解析时,此定义将用于从区块内容中提取数据。所有匹配项都会通过`attributes`属性提供给您的区块。
|
||||
|
||||
该解析过程可概括为:
|
||||
|
||||
1. 从`source`中提取值
|
||||
2. 检查值是否匹配`type`,或是`enum`值之一
|
||||
|
||||
*示例*:使用上述属性定义,在`edit`函数中可用的属性。
|
||||
|
||||
```js
|
||||
function YourBlockEdit( { attributes } ) {
|
||||
return (
|
||||
<p>URL是{ attributes.url },标题是{ attributes.title },尺寸是{ attributes.size }。</p>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
区块需负责使用`save`函数确保所有带`source`字段的属性按照属性定义保存。此过程非自动执行。
|
||||
|
||||
没有`source`的属性将自动保存在区块[注释分隔符](/docs/explanations/architecture/key-concepts.md#data-attributes)中。
|
||||
|
||||
例如,使用上述属性定义时,您需要确保`save`函数包含与`url`属性对应的img标签。`title`和`size`属性将保存在注释分隔符中。
|
||||
|
||||
*示例*:包含`url`属性的`save`函数示例
|
||||
|
||||
```js
|
||||
function YourBlockSave( { attributes } ) {
|
||||
return (
|
||||
<img src={ attributes.url } />
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
保存的HTML将在注释分隔符中包含`title`和`size`,在`img`节点中包含`url`。
|
||||
|
||||
```html
|
||||
<!-- block:your-block {"title":"hello world","size":"large"} -->
|
||||
<img src="/image.jpg" />
|
||||
<!-- /block:your-block -->
|
||||
```
|
||||
|
||||
若属性随时间变化,可通过[区块弃用](/docs/reference-guides/block-api/block-deprecation.md)来迁移旧属性或完全移除。
|
||||
|
||||
## 类型验证
|
||||
|
||||
`type`指明属性存储的数据类型。它不表示数据存储位置(由`source`字段定义)。
|
||||
|
||||
除非提供`enum`,否则`type`是必需的。`type`可与`enum`同时使用。
|
||||
|
||||
`type`字段必须是以下之一:
|
||||
|
||||
- `null`
|
||||
- `boolean`
|
||||
- `object`
|
||||
- `array`
|
||||
- `string`
|
||||
- `integer`
|
||||
- `number`(与`integer`相同)
|
||||
|
||||
注意:`object`的有效性由您的`source`决定。示例可参阅下文的`query`详情。
|
||||
|
||||
## 枚举验证
|
||||
|
||||
属性可定义为固定值集合中的一个值。通过包含允许值数组的`enum`来指定:
|
||||
|
||||
*示例*:`enum`示例。
|
||||
|
||||
```js
|
||||
{
|
||||
size: {
|
||||
enum: [ 'large', 'small', 'tiny' ]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 值来源
|
||||
|
||||
属性来源用于定义如何从已保存的文章内容中提取属性值。它们提供了一种从已保存标记到区块JavaScript表示的映射机制。
|
||||
|
||||
可用的`source`值包括:
|
||||
- `(无值)`- 未指定`source`时,数据存储在区块的[注释分隔符](/docs/explanations/architecture/key-concepts.md#data-attributes)中
|
||||
- `attribute`- 数据存储在HTML元素属性中
|
||||
- `text`- 数据存储在HTML文本中
|
||||
- `html`- 数据以HTML形式存储(通常由`RichText`使用)
|
||||
- `query`- 数据以对象数组形式存储
|
||||
- `meta`- 数据存储在文章元数据中(已弃用)
|
||||
|
||||
`source`字段通常与`selector`字段结合使用。若未指定选择器参数,源定义将针对区块根节点运行。若指定选择器参数,则将针对区块内的匹配元素运行。
|
||||
|
||||
`selector`可以是HTML标签,或任何可通过[querySelector](https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelector)查询的内容,例如类或id属性。下方提供了示例。
|
||||
|
||||
例如,`img`选择器将匹配`img`元素,而`img.class`将匹配具有`class`类的`img`元素。
|
||||
|
||||
在底层实现中,属性来源是[hpq](https://github.com/aduth/hpq)库功能的超集,该小型库用于将HTML标记解析和查询为对象形态。
|
||||
|
||||
总结而言,`source`决定数据在内容中的存储位置,而`type`决定数据的类型。为减少存储数据量,通常建议尽可能将数据存储在HTML中而非注释分隔符内的属性中。
|
||||
|
||||
### 元数据源(已弃用)
|
||||
|
||||
<div class="callout callout-alert">
|
||||
虽然属性可从文章的元数据中获取,但元数据属性源已被视为弃用;应改用 <a href="https://github.com/WordPress/gutenberg/blob/c367c4e2765f9e6b890d1565db770147efca5d66/packages/core-data/src/entity-provider.js">EntityProvider 及相关钩子 API</a>,如 <a href="https://developer.wordpress.org/block-editor/how-to-guides/metabox/#step-2-add-meta-block">创建元数据块指南</a> 中所示。
|
||||
</div>
|
||||
|
||||
属性可从文章的元数据中获取,而非从已保存文章内容中的块表示中获取。为此,需要为属性在 `meta` 键下指定其对应的元数据键。
|
||||
|
||||
属性定义:
|
||||
```js
|
||||
{
|
||||
author: {
|
||||
type: 'string',
|
||||
source: 'meta',
|
||||
meta: 'author'
|
||||
},
|
||||
},
|
||||
```
|
||||
|
||||
从此处开始,元数据属性可以通过与任何属性相同的接口由块读取和写入:
|
||||
|
||||
```js
|
||||
edit( { attributes, setAttributes } ) {
|
||||
function onChange( event ) {
|
||||
setAttributes( { author: event.target.value } );
|
||||
}
|
||||
|
||||
return <input value={ attributes.author } onChange={ onChange } type="text" />;
|
||||
},
|
||||
```
|
||||
|
||||
#### 注意事项
|
||||
|
||||
默认情况下,元字段将从文章对象的元数据中排除。可以通过显式使字段可见来规避此问题:
|
||||
|
||||
```php
|
||||
function gutenberg_my_block_init() {
|
||||
register_post_meta( 'post', 'author', array(
|
||||
'show_in_rest' => true,
|
||||
) );
|
||||
}
|
||||
add_action( 'init', 'gutenberg_my_block_init' );
|
||||
```
|
||||
|
||||
此外,请注意 WordPress 默认行为为:
|
||||
|
||||
- 不将元数据视为唯一,而是返回值的数组;
|
||||
- 将该数据视为字符串。
|
||||
|
||||
如果不希望出现上述任一行为,可以在相同的 `register_post_meta` 调用中补充 `single` 和/或 `type` 参数,如下所示:
|
||||
|
||||
```php
|
||||
function gutenberg_my_block_init() {
|
||||
register_post_meta( 'post', 'author_count', array(
|
||||
'show_in_rest' => true,
|
||||
'single' => true,
|
||||
'type' => 'integer',
|
||||
) );
|
||||
}
|
||||
add_action( 'init', 'gutenberg_my_block_init' );
|
||||
```
|
||||
|
||||
如果希望在属性中使用对象或数组,可以注册一个 `string` 属性类型并使用 JSON 作为中间格式。在保存之前将结构化数据序列化为 JSON,然后在服务器上反序列化 JSON 字符串。请注意,您需要负责数据的完整性;确保正确清理数据、处理缺失数据等。
|
||||
|
||||
最后,请确保在设置属性时尊重数据的类型,因为框架不会自动执行元数据的类型转换。块属性中的类型错误将导致文章即使在保存后仍保持“脏”状态(参见 `isEditedPostDirty`、`hasEditedAttributes`)。例如,如果 `authorCount` 是整数类型,请记住事件处理程序可能会传递不同类型的数据,因此应显式转换值:
|
||||
|
||||
```js
|
||||
function onChange( event ) {
|
||||
props.setAttributes( { authorCount: Number( event.target.value ) } );
|
||||
}
|
||||
```
|
||||
|
||||
## 默认值
|
||||
|
||||
块属性可以包含默认值,当 `type` 和 `source` 与块内容中的任何内容不匹配时,将使用该值。
|
||||
|
||||
该值由 `default` 字段提供,并且该值应与属性的预期格式匹配。
|
||||
|
||||
_示例_:`default` 值的示例。
|
||||
|
||||
```js
|
||||
{
|
||||
type: 'string',
|
||||
default: 'hello world'
|
||||
}
|
||||
```
|
||||
|
||||
```js
|
||||
{
|
||||
type: 'array',
|
||||
default: [
|
||||
{ "url": "https://lorempixel.com/1200/800/", "alt": "大图" },
|
||||
{ "url": "https://lorempixel.com/50/50/", "alt": "小图" }
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
```js
|
||||
{
|
||||
type: 'object',
|
||||
default: {
|
||||
width: 100,
|
||||
title: '标题'
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 角色
|
||||
|
||||
`role` 属性将属性指定为特定概念类型。此属性可应用于任何属性,以提供关于应如何处理该属性的语义含义。
|
||||
|
||||
使用 `content` 将属性指定为用户可编辑的内容。在特殊情况下(例如仅内容锁定),标记为 `content` 的块可能被启用为特权编辑。
|
||||
使用 `local` 将属性标记为临时且不可持久化的。标记为 `local` 的属性会被块序列化器忽略,并且永远不会保存到文章内容中。
|
||||
|
||||
_示例_:段落块使用的 `content` 角色
|
||||
|
||||
```js
|
||||
{
|
||||
content: {
|
||||
type: 'string',
|
||||
source: 'html',
|
||||
selector: 'p',
|
||||
role: 'content',
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
_示例_:用于临时数据的 `local` 角色。
|
||||
|
||||
```js
|
||||
{
|
||||
blob: {
|
||||
type: 'string',
|
||||
role: 'local',
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
更多信息请参阅 [WordPress 6.7 开发说明](https://make.wordpress.org/core/2024/10/20/miscellaneous-block-editor-changes-in-wordpress-6-7/#stabilized-role-property-for-block-attributes)。
|
||||
|
||||
### `attribute` 数据源
|
||||
|
||||
使用 `attribute` 数据源可从标记中提取属性值。通过必须提供的 `attribute` 字段指定需要提取的属性。
|
||||
|
||||
_示例_:从区块标记中的图片元素提取 `src` 属性。
|
||||
|
||||
保存内容:
|
||||
```html
|
||||
<div>
|
||||
区块内容
|
||||
|
||||
<img src="https://lorempixel.com/1200/800/" />
|
||||
</div>
|
||||
```
|
||||
|
||||
属性定义:
|
||||
```js
|
||||
{
|
||||
url: {
|
||||
type: 'string',
|
||||
source: 'attribute',
|
||||
selector: 'img',
|
||||
attribute: 'src',
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
区块中可用的属性:
|
||||
```js
|
||||
{ "url": "https://lorempixel.com/1200/800/" }
|
||||
```
|
||||
|
||||
大多数标记中的属性都是字符串类型。HTML中的数值属性仍会以字符串形式存储,且不会自动转换。
|
||||
|
||||
_示例_:从区块标记中的图片元素提取 `width` 属性。
|
||||
|
||||
保存内容:
|
||||
```html
|
||||
<div>
|
||||
区块内容
|
||||
|
||||
<img src="https://lorempixel.com/1200/800/" width="50" />
|
||||
</div>
|
||||
```
|
||||
|
||||
属性定义:
|
||||
```js
|
||||
{
|
||||
width: {
|
||||
type: 'string',
|
||||
source: 'attribute',
|
||||
selector: 'img',
|
||||
attribute: 'width',
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
区块中可用的属性:
|
||||
```js
|
||||
{ "width": "50" }
|
||||
```
|
||||
|
||||
唯一例外是检查属性是否存在的情况(例如检查 `button` 上的 `disabled` 属性)。此时可使用 `boolean` 类型,存储值将转换为布尔值。
|
||||
|
||||
_示例_:从区块标记中的按钮元素提取 `disabled` 属性。
|
||||
|
||||
保存内容:
|
||||
```html
|
||||
<div>
|
||||
区块内容
|
||||
|
||||
<button type="button" disabled>按钮</button>
|
||||
</div>
|
||||
```
|
||||
|
||||
属性定义:
|
||||
```js
|
||||
{
|
||||
disabled: {
|
||||
type: 'boolean',
|
||||
source: 'attribute',
|
||||
selector: 'button',
|
||||
attribute: 'disabled',
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
区块中可用的属性:
|
||||
```js
|
||||
{ "disabled": true }
|
||||
```
|
||||
|
||||
### `text` 数据源
|
||||
|
||||
使用 `text` 可从标记中提取内部文本。注意返回的HTML内容遵循 [`textContent`](https://developer.mozilla.org/zh-CN/docs/Web/API/Node/textContent) 规则。
|
||||
|
||||
_示例_:从区块标记中的 figcaption 元素提取 `content` 属性。
|
||||
|
||||
保存内容:
|
||||
```html
|
||||
<figure>
|
||||
<img src="/image.jpg" />
|
||||
|
||||
<figcaption>figcaption 元素的内部文本</figcaption>
|
||||
</figure>
|
||||
```
|
||||
|
||||
属性定义:
|
||||
```js
|
||||
{
|
||||
content: {
|
||||
type: 'string',
|
||||
source: 'text',
|
||||
selector: 'figcaption',
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
区块中可用的属性:
|
||||
```js
|
||||
{ "content": "figcaption 元素的内部文本" }
|
||||
```
|
||||
|
||||
另一个使用 `text` 数据源,通过 `.my-content` 类选择器提取文本的示例:
|
||||
|
||||
_示例_:从区块标记中具有 `.my-content` 类的元素提取 `content` 属性。
|
||||
|
||||
保存内容:
|
||||
```html
|
||||
<div>
|
||||
<img src="/image.jpg" />
|
||||
|
||||
<p class="my-content">.my-content 类的内部文本</p>
|
||||
</div>
|
||||
```
|
||||
|
||||
属性定义:
|
||||
```js
|
||||
{
|
||||
content: {
|
||||
type: 'string',
|
||||
source: 'text',
|
||||
selector: '.my-content',
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
区块中可用的属性:
|
||||
```js
|
||||
{ "content": ".my-content 类的内部文本" }
|
||||
```
|
||||
|
||||
### `html` 数据源
|
||||
|
||||
使用 `html` 可从标记中提取内部HTML。注意返回的文本内容遵循 [`innerHTML`](https://developer.mozilla.org/zh-CN/docs/Web/API/Element/innerHTML) 规则。
|
||||
|
||||
_示例_:从区块标记中的 figcaption 元素提取 `content` 属性。
|
||||
|
||||
保存内容:
|
||||
```html
|
||||
<figure>
|
||||
<img src="/image.jpg" />
|
||||
|
||||
<figcaption><strong>figcaption</strong> 元素的内部文本</figcaption>
|
||||
</figure>
|
||||
```
|
||||
|
||||
属性定义:
|
||||
```js
|
||||
{
|
||||
content: {
|
||||
type: 'string',
|
||||
source: 'html',
|
||||
selector: 'figcaption',
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
区块中可用的属性:
|
||||
```js
|
||||
{ "content": "<strong>figcaption</strong> 元素的内部文本" }
|
||||
```
|
||||
|
||||
### `query` 数据源
|
||||
|
||||
使用 `query` 可从标记中提取值数组。数组条目由 `selector` 参数决定,区块内每个匹配元素都会对应一个条目,其结构由第二个参数(属性源对象)定义。
|
||||
|
||||
`query` 字段实际上是嵌套的区块属性定义。虽然可以进一步嵌套(但不一定推荐这样做)。
|
||||
|
||||
_示例_:从区块标记中的每个图片元素提取 `src` 和 `alt` 属性。
|
||||
|
||||
保存内容:
|
||||
```html
|
||||
<div>
|
||||
<img src="https://lorempixel.com/1200/800/" alt="大图" />
|
||||
<img src="https://lorempixel.com/50/50/" alt="小图" />
|
||||
</div>
|
||||
```
|
||||
|
||||
属性定义:
|
||||
```js
|
||||
{
|
||||
images: {
|
||||
type: 'array',
|
||||
source: 'query',
|
||||
selector: 'img',
|
||||
query: {
|
||||
url: {
|
||||
type: 'string',
|
||||
source: 'attribute',
|
||||
attribute: 'src',
|
||||
},
|
||||
alt: {
|
||||
type: 'string',
|
||||
source: 'attribute',
|
||||
attribute: 'alt',
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
区块中可用的属性:
|
||||
```js
|
||||
{
|
||||
"images": [
|
||||
{ "url": "https://lorempixel.com/1200/800/", "alt": "大图" },
|
||||
{ "url": "https://lorempixel.com/50/50/", "alt": "小图" }
|
||||
]
|
||||
}
|
||||
```
|
||||
327
reference-guides/block-api/block-bindings.md
Normal file
327
reference-guides/block-api/block-bindings.md
Normal file
@@ -0,0 +1,327 @@
|
||||
#### setValues 函数
|
||||
|
||||
`setValues` 函数用于更新绑定区块源的所有值。它接收一个包含以下属性的 `object` 作为参数:
|
||||
|
||||
- `bindings` 返回特定源的绑定对象。该对象必须以属性作为键,值可以是 `string` 或包含参数的 `object`。此对象包含一个 `newValue` 属性,用于存储用户的输入。
|
||||
- `clientId` 返回一个 `string`,表示当前区块的客户端 ID。
|
||||
- `context` 返回一个 `object`,表示当前区块的上下文,定义在 `usesContext` 属性中。[关于区块上下文的更多信息](https://developer.wordpress.org/block-editor/reference-guides/block-api/block-context/)。
|
||||
- `dispatch` 返回一个 `object`,包含存储的操作创建器。[关于 dispatch 的更多信息](https://developer.wordpress.org/block-editor/reference-guides/packages/packages-data/#dispatch)。
|
||||
- `select` 返回一个 `object`,包含给定存储的选择器。[更多信息请参阅文档](https://developer.wordpress.org/block-editor/reference-guides/packages/packages-data/#select)。
|
||||
|
||||
#### 编辑器注册核心示例
|
||||
|
||||
核心中有几个示例可供参考:
|
||||
|
||||
- 文章元数据。[源代码](https://github.com/WordPress/gutenberg/blob/5afd6c27bfba2be2e06b502257753fbfff1ae9f0/packages/editor/src/bindings/post-meta.js#L74-L146)
|
||||
- 模式覆盖。[源代码](https://github.com/WordPress/gutenberg/blob/5afd6c27bfba2be2e06b502257753fbfff1ae9f0/packages/editor/src/bindings/pattern-overrides.js#L8-L100)
|
||||
|
||||
## 注销源
|
||||
|
||||
_**注意:**自 WordPress 6.7 起。_
|
||||
|
||||
`unregisterBlockBindingsSource` 通过提供名称注销一个区块绑定源。
|
||||
|
||||
```js
|
||||
import { unregisterBlockBindingsSource } from '@wordpress/blocks';
|
||||
|
||||
unregisterBlockBindingsSource( 'plugin/my-custom-source' );
|
||||
```
|
||||
|
||||
## 获取所有源
|
||||
|
||||
_**注意:**自 WordPress 6.7 起。_
|
||||
|
||||
`getBlockBindingsSources` 返回所有已注册的区块绑定源。
|
||||
|
||||
```js
|
||||
import { getBlockBindingsSources } from '@wordpress/blocks';
|
||||
|
||||
const registeredSources = getBlockBindingsSources();
|
||||
```
|
||||
|
||||
## 获取特定源
|
||||
|
||||
_**注意:**自 WordPress 6.7 起。_
|
||||
|
||||
`getBlockBindingsSource` 通过名称返回特定的区块绑定源。
|
||||
|
||||
```js
|
||||
import { getBlockBindingsSource } from '@wordpress/blocks';
|
||||
|
||||
const blockBindingsSource = getBlockBindingsSource( 'plugin/my-custom-source' );
|
||||
```
|
||||
|
||||
## 区块绑定工具
|
||||
|
||||
_**注意:**自 WordPress 6.7 起。_
|
||||
|
||||
`useBlockBindingUtils` 是一个包含两个辅助函数的钩子,允许开发者轻松编辑 `metadata.bindings` 属性。
|
||||
|
||||
它接受一个 `clientId` 字符串作为参数,如果未设置,函数将使用上下文中的当前区块客户端 ID。
|
||||
|
||||
示例:
|
||||
|
||||
```js
|
||||
import { useBlockBindingsUtils } from '@wordpress/block-editor';
|
||||
|
||||
const { updateBlockBindings } = useBlockBindingsUtils('my-block-client-id-12345');
|
||||
...
|
||||
```
|
||||
|
||||
### updateBlockBindings
|
||||
|
||||
`updateBlockBindings` 的工作方式类似于 `updateBlockAttributes`,可用于创建、更新或删除特定连接。
|
||||
|
||||
```js
|
||||
import { useBlockBindingsUtils } from '@wordpress/block-editor';
|
||||
|
||||
const { updateBlockBindings } = useBlockBindingsUtils();
|
||||
|
||||
function updateBlockBindingsURLSource( url ) {
|
||||
updateBlockBindings({
|
||||
url: {
|
||||
source: 'myplugin/new-source',
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 从 url 属性中移除绑定。
|
||||
function removeBlockBindingsURLSource() {
|
||||
updateBlockBindings( { url: undefined } );
|
||||
}
|
||||
```
|
||||
|
||||
### removeAllBlockBindings
|
||||
|
||||
`removeAllBlockBindings` 将通过移除 `metadata.bindings` 属性来删除区块中的所有现有连接。
|
||||
|
||||
```js
|
||||
import { useBlockBindingsUtils } from '@wordpress/block-editor';
|
||||
|
||||
const { removeAllBlockBindings } = useBlockBindingsUtils();
|
||||
|
||||
function clearBlockBindings() {
|
||||
removeAllBlockBindings();
|
||||
}
|
||||
```
|
||||
|
||||
#### 服务器注册核心示例
|
||||
|
||||
核心代码库中有几个可用作参考的示例:
|
||||
|
||||
- 文章元数据。[源代码](https://github.com/WordPress/wordpress-develop/blob/trunk/src/wp-includes/block-bindings/post-meta.php)
|
||||
- 模式覆盖。[源代码](https://github.com/WordPress/wordpress-develop/blob/trunk/src/wp-includes/block-bindings/pattern-overrides.php)
|
||||
- 二十五主题。[源代码](https://github.com/WordPress/wordpress-develop/blob/trunk/src/wp-content/themes/twentytwentyfive/functions.php)
|
||||
|
||||
### 编辑器注册
|
||||
|
||||
_**注意:** 自WordPress 6.7起支持_
|
||||
|
||||
客户端编辑器注册允许定义绑定区块在获取值或编辑值时的行为。
|
||||
|
||||
注册自定义源的函数是 `registerBlockBindingsSource( args )`:
|
||||
|
||||
- `args`:包含以下结构的`对象`:
|
||||
- `name`:具有唯一性且机器可读名称的`字符串`
|
||||
- `label`:自定义源的人类可读名称`字符串`。若已在服务器端定义,服务器标签将被此标签覆盖,此时不建议在此重复定义(可选)
|
||||
- `usesContext`:自定义源可能需要的区块上下文`数组`。若已在服务器端定义,则不应在此重复定义(可选)
|
||||
- `getValues`:从源获取值的`函数`(可选)
|
||||
- `setValues`:允许更新与源连接值的`函数`(可选)
|
||||
- `canUserEditValue`:判断用户是否可以编辑值的`函数`。默认情况下用户无法编辑(可选)
|
||||
|
||||
此示例将在编辑器中显示自定义文章元数据日期,若不存在则显示当前日期。用户可以编辑日期值。(注意:此示例未将用户输入格式化为日期——仅用于教学目的)
|
||||
|
||||
```js
|
||||
import {
|
||||
registerBlockBindingsSource,
|
||||
} from '@wordpress/blocks';
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import { store as coreDataStore } from '@wordpress/core-data';
|
||||
|
||||
registerBlockBindingsSource( {
|
||||
name: 'wpmovies/visualization-date',
|
||||
label: __( '观影日期', 'custom-bindings' ), // 可跳过标签定义,因已在前面示例的服务器端定义
|
||||
usesContext: [ 'postType' ], // 可跳过postId定义,因已在前面示例的服务器端定义
|
||||
getValues( { select, context } ) {
|
||||
let wpMoviesVisualizationDate;
|
||||
const { getEditedEntityRecord } = select( coreDataStore );
|
||||
if ( context?.postType && context?.postId ) {
|
||||
wpMoviesVisualizationDate = getEditedEntityRecord(
|
||||
'postType',
|
||||
context?.postType,
|
||||
context?.postId
|
||||
).meta?.wp_movies_visualization_date;
|
||||
}
|
||||
if ( wpMoviesVisualizationDate ) {
|
||||
return {
|
||||
content: wpMoviesVisualizationDate,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
content: new Date().toLocaleDateString( 'zh-CN' ),
|
||||
};
|
||||
},
|
||||
setValues( { select, dispatch, context, bindings } ) {
|
||||
dispatch( coreDataStore ).editEntityRecord(
|
||||
'postType',
|
||||
context?.postType,
|
||||
context?.postId,
|
||||
{
|
||||
meta: {
|
||||
wp_movies_visualization_date: bindings?.content?.newValue,
|
||||
},
|
||||
}
|
||||
);
|
||||
},
|
||||
canUserEditValue( { select, context } ) {
|
||||
return true;
|
||||
},
|
||||
} );
|
||||
```
|
||||
|
||||
#### getValues函数
|
||||
|
||||
`getValues`函数在区块加载时从源获取值。它接收包含以下属性的`对象`作为参数:
|
||||
|
||||
- `bindings` 返回特定源的绑定对象。必须以属性为键,值可以是`字符串`或带参数的`对象`
|
||||
- `clientId` 返回当前区块客户端ID的`字符串`
|
||||
- `context` 返回在`usesContext`属性中定义的当前区块上下文`对象`。[关于区块上下文的更多信息](https://developer.wordpress.org/block-editor/reference-guides/block-api/block-context/)
|
||||
- `select` 返回给定存储库选择器的`对象`。[详细文档](https://developer.wordpress.org/block-editor/reference-guides/packages/packages-data/#select)
|
||||
|
||||
该函数必须返回具有以下结构的`对象`:
|
||||
`{ '区块属性': 值 }`
|
||||
|
||||
# 数据绑定
|
||||
|
||||
<div class="callout callout-alert">
|
||||
区块绑定 API 仅适用于 WordPress 6.5 及以上版本。
|
||||
</div>
|
||||
|
||||
区块绑定 API 允许您将动态数据"绑定"到区块的属性上,这些数据最终会反映在输出到前端浏览器的 HTML 标记中。
|
||||
|
||||
例如,可以将图片区块的 `url` 属性连接到从外部 API 返回随机图片的函数。
|
||||
|
||||
```html
|
||||
<!-- wp:image {
|
||||
"metadata":{
|
||||
"bindings":{
|
||||
"url":{
|
||||
"source":"my-plugin/get-random-images"
|
||||
}
|
||||
}
|
||||
}
|
||||
} -->
|
||||
```
|
||||
|
||||
## 兼容区块及其属性
|
||||
|
||||
目前并非所有区块属性都支持数据绑定。虽然正在努力提升兼容性,但当前支持的列表如下:
|
||||
|
||||
| 支持区块 | 支持属性 |
|
||||
| ---------------- | -------------------- |
|
||||
| 段落 | content |
|
||||
| 标题 | content |
|
||||
| 图片 | id, url, title, alt |
|
||||
| 按钮 | text, url, linkTarget, rel |
|
||||
|
||||
## 注册自定义数据源
|
||||
|
||||
注册数据源需要至少定义 `name`(名称)、`label`(标签)和 `callback`(回调函数),该函数从数据源获取值并传递给区块属性。
|
||||
|
||||
数据源注册后,任何支持的区块都可以通过配置 `metadata.bindings` 属性来读取该数据源的值。
|
||||
|
||||
注册可以通过 PHP 在服务器端完成,也可以通过 JavaScript 在编辑器端完成,两者可以共存。
|
||||
|
||||
服务器端注册定义的标签将被编辑器端定义的标签覆盖。
|
||||
|
||||
### 服务器端注册
|
||||
|
||||
服务器端注册允许应用一个回调函数,该函数将在前端为绑定属性执行。
|
||||
|
||||
注册自定义数据源的函数是 `register_block_bindings_source($name, $args)`:
|
||||
|
||||
- `name`:`string`,设置自定义数据源的唯一 ID。
|
||||
- `args`:`array`,包含:
|
||||
- `label`:`string`,自定义数据源的可读名称。
|
||||
- `uses_context`:`array`,传递给回调函数的区块上下文(可选)。
|
||||
- `get_value_callback`:`function`,在绑定区块的渲染函数中运行。它接受三个参数:`source_args`、`block_instance` 和 `attribute_name`。此值可以通过 `block_bindings_source_value` 过滤器进行修改。
|
||||
|
||||
注意,`register_block_bindings_source()` 应通过附加到 `init` 钩子的处理程序调用。
|
||||
|
||||
以下是一个示例:
|
||||
|
||||
```php
|
||||
add_action(
|
||||
'init',
|
||||
function () {
|
||||
register_block_bindings_source(
|
||||
'wpmovies/visualization-date',
|
||||
array(
|
||||
'label' => __( 'Visualization Date', 'custom-bindings' ),
|
||||
'get_value_callback' => function ( array $source_args, $block_instance ) {
|
||||
$post_id = $block_instance->context['postId'];
|
||||
if ( isset( $source_args['key'] ) ) {
|
||||
return get_post_meta( $post_id, $source_args['key'], true );
|
||||
}
|
||||
},
|
||||
'uses_context' => array( 'postId' ),
|
||||
)
|
||||
);
|
||||
}
|
||||
);
|
||||
```
|
||||
|
||||
此示例需要注册一个 `post_meta`,并且可以使用过滤器返回默认的 `$visualization_date` 值,该值将在下一个标题中显示。
|
||||
|
||||
```php
|
||||
add_action(
|
||||
'init',
|
||||
function () {
|
||||
register_meta(
|
||||
'post',
|
||||
'wp_movies_visualization_date',
|
||||
array(
|
||||
'show_in_rest' => true,
|
||||
'single' => true,
|
||||
'type' => 'string',
|
||||
'label' => __( 'Movie visualization date', 'custom-bindings' ),
|
||||
)
|
||||
);
|
||||
}
|
||||
);
|
||||
```
|
||||
|
||||
<div class="callout callout-alert">
|
||||
<strong>注意:</strong>以下划线开头的文章元键(例如 `_example_key`)是受保护的,不能用于区块绑定。此外,文章元必须通过 `show_in_rest = true` 注册才能在区块绑定 API 中使用。
|
||||
</div>
|
||||
|
||||
#### 区块绑定数据源值过滤器
|
||||
|
||||
_**注意:**自 WordPress 6.7 起。_
|
||||
|
||||
`get_value_callback` 返回的值可以通过 `block_bindings_source_value` 过滤器进行修改。
|
||||
该过滤器具有以下参数:
|
||||
|
||||
- `value`:要过滤的值。
|
||||
- `name`:数据源的名称。
|
||||
- `source_args`:包含数据源参数的 `array`。
|
||||
- `block_instance`:区块实例对象。
|
||||
- `attribute_name`:属性名称。
|
||||
|
||||
示例:
|
||||
|
||||
```php
|
||||
function wpmovies_format_visualization_date( $value, $name ) {
|
||||
// 防止此过滤器应用于其他数据源。
|
||||
if ( $name !== 'wpmovies/visualization-date' ) {
|
||||
return $value;
|
||||
}
|
||||
if ( ! $value ) {
|
||||
return date( 'm/d/Y' );
|
||||
}
|
||||
return date( 'm/d/Y', strtotime( $value ) );
|
||||
}
|
||||
|
||||
add_filter( 'block_bindings_source_value', 'wpmovies_format_visualization_date', 10, 2 );
|
||||
```
|
||||
168
reference-guides/block-api/block-context.md
Normal file
168
reference-guides/block-api/block-context.md
Normal file
@@ -0,0 +1,168 @@
|
||||
# 上下文
|
||||
|
||||
区块上下文是一项功能,允许祖先区块提供可供其自身层次结构内的后代区块使用的值。这些后代区块可以继承这些值,而无需依赖硬编码值,也无需明确知晓提供这些值的区块。
|
||||
|
||||
这在全站编辑中尤其有用。例如,某个区块的内容可能取决于显示它的文章上下文。博客目录模板可能显示许多不同文章的摘要。通过使用区块上下文,仍然可以有一个单一的“文章摘要”区块,根据继承的文章ID显示文章内容。
|
||||
|
||||
如果您熟悉 [React Context](https://react.dev/learn/passing-data-deeply-with-context),区块上下文采用了许多相同的理念。实际上,客户端区块编辑器对区块上下文的实现是 React Context 的一个非常简单的应用。区块上下文在服务器端 `render_callback` 实现中也受支持,如下面的示例所示。
|
||||
|
||||
## 定义区块上下文
|
||||
|
||||
区块上下文在区块的注册设置中定义。一个区块可以提供一个上下文值,或者使用它希望继承的值。
|
||||
|
||||
### 提供区块上下文
|
||||
|
||||
区块可以通过在其注册设置中分配一个 `providesContext` 属性来提供上下文值。这是一个将上下文名称映射到区块自身某个属性的对象。该属性值对应的值将提供给后代区块,并可以通过相同的上下文名称引用。目前,区块上下文仅支持源自区块自身属性的值。未来可能会增强以支持其他上下文值来源。
|
||||
|
||||
```js
|
||||
attributes: {
|
||||
recordId: {
|
||||
type: 'number',
|
||||
},
|
||||
},
|
||||
|
||||
providesContext: {
|
||||
'my-plugin/recordId': 'recordId',
|
||||
},
|
||||
```
|
||||
|
||||
有关完整示例,请参阅下面的部分。
|
||||
|
||||
#### 包含命名空间
|
||||
|
||||
如上例所示,建议您在上下文键的名称中包含命名空间,以避免与其他插件或 WordPress 提供的默认上下文值发生潜在冲突。上下文命名空间应特定于您的插件,并且在大多数情况下可以与区块本身的名称相同。
|
||||
|
||||
### 使用区块上下文
|
||||
|
||||
区块可以通过在其注册设置中分配一个 `usesContext` 属性来从祖先提供者继承上下文值。这应分配为区块希望继承的上下文名称数组。
|
||||
|
||||
```js
|
||||
registerBlockType('my-plugin/record-title', {
|
||||
title: 'Record Title',
|
||||
category: 'widgets',
|
||||
|
||||
usesContext: ['my-plugin/recordId'],
|
||||
|
||||
```
|
||||
|
||||
## 使用区块上下文
|
||||
|
||||
一旦区块定义了它希望继承的上下文,就可以在 `edit`(JavaScript)和 `render_callback`(PHP)的实现中访问它。它作为上下文值的对象(JavaScript)或关联数组(PHP)提供,这些值已为区块定义。请注意,只有在区块明确定义了希望继承该值的情况下,上下文值才会可用。
|
||||
|
||||
注意:区块上下文不适用于 `save`。
|
||||
|
||||
### JavaScript
|
||||
|
||||
```js
|
||||
registerBlockType('my-plugin/record-title', {
|
||||
|
||||
edit({ context }) {
|
||||
return 'The record ID: ' + context['my-plugin/recordId'];
|
||||
},
|
||||
|
||||
```
|
||||
|
||||
### PHP
|
||||
|
||||
区块的上下文值可以从 `$block` 参数的 `context` 属性中获取,该参数作为第三个参数传递给 `render_callback` 函数。
|
||||
|
||||
```php
|
||||
register_block_type( 'my-plugin/record-title', array(
|
||||
'render_callback' => function( $attributes, $content, $block ) {
|
||||
return 'The current record ID is: ' . $block->context['my-plugin/recordId'];
|
||||
},
|
||||
) );
|
||||
```
|
||||
|
||||
## 示例
|
||||
|
||||
1. 创建一个 `record` 区块。
|
||||
|
||||
```
|
||||
npm init @wordpress/block --namespace my-plugin record
|
||||
cd record
|
||||
```
|
||||
|
||||
2. 编辑 `src/index.js`。在 `registerBlockType` 函数中插入 `recordId` 属性和 `providesContext` 属性,并在底部添加 `record-title` 区块的注册:
|
||||
|
||||
```js
|
||||
registerBlockType( 'my-plugin/record', {
|
||||
// ... 省略 ...
|
||||
|
||||
attributes: {
|
||||
recordId: {
|
||||
type: 'number',
|
||||
},
|
||||
},
|
||||
|
||||
providesContext: {
|
||||
'my-plugin/recordId': 'recordId',
|
||||
},
|
||||
|
||||
/**
|
||||
* @see ./edit.js
|
||||
*/
|
||||
edit: Edit,
|
||||
|
||||
/**
|
||||
* @see ./save.js
|
||||
*/
|
||||
save,
|
||||
} );
|
||||
|
||||
registerBlockType( 'my-plugin/record-title', {
|
||||
title: 'Record Title',
|
||||
category: 'widgets',
|
||||
|
||||
usesContext: [ 'my-plugin/recordId' ],
|
||||
|
||||
edit( { context } ) {
|
||||
return 'The record ID: ' + context[ 'my-plugin/recordId' ];
|
||||
},
|
||||
|
||||
save() {
|
||||
return null;
|
||||
},
|
||||
} );
|
||||
```
|
||||
|
||||
3. 编辑 `record` 区块的 `src/edit.js`。将 `Edit` 函数替换为以下代码:
|
||||
|
||||
```js
|
||||
import { TextControl } from '@wordpress/components';
|
||||
import { InnerBlocks } from '@wordpress/block-editor';
|
||||
|
||||
export default function Edit( props ) {
|
||||
const MY_TEMPLATE = [ [ 'my-plugin/record-title', {} ] ];
|
||||
const {
|
||||
attributes: { recordId },
|
||||
setAttributes,
|
||||
} = props;
|
||||
return (
|
||||
<div>
|
||||
<TextControl
|
||||
__nextHasNoMarginBottom
|
||||
__next40pxDefaultSize
|
||||
label={ __( 'Record ID' ) }
|
||||
value={ recordId }
|
||||
onChange={ ( val ) =>
|
||||
setAttributes( { recordId: Number( val ) } )
|
||||
}
|
||||
/>
|
||||
<InnerBlocks template={ MY_TEMPLATE } templateLock="all" />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
4. 编辑 `record` 区块的 `src/save.js`。将 `save` 函数替换为以下代码:
|
||||
|
||||
```js
|
||||
export default function save( props ) {
|
||||
return <p>The record ID: { props.attributes.recordId }</p>;
|
||||
}
|
||||
```
|
||||
|
||||
5. 创建一篇新文章并添加 `record` 区块。如果您在文本框中输入一个数字,您会看到其下方的 `record-title` 区块中显示相同的数字。
|
||||
|
||||

|
||||
203
reference-guides/block-api/block-deprecation.md
Normal file
203
reference-guides/block-api/block-deprecation.md
Normal file
@@ -0,0 +1,203 @@
|
||||
## 修改属性集
|
||||
|
||||
有时需要更新属性集,以重命名或修改旧属性。
|
||||
|
||||
**示例**
|
||||
|
||||
```js
|
||||
const { registerBlockType } = wp.blocks;
|
||||
|
||||
registerBlockType( 'gutenberg/block-with-deprecated-version', {
|
||||
// ... 其他区块属性
|
||||
|
||||
attributes: {
|
||||
content: {
|
||||
type: 'string',
|
||||
default: '随机值',
|
||||
},
|
||||
},
|
||||
|
||||
save( props ) {
|
||||
return <div>{ props.attributes.content }</div>;
|
||||
},
|
||||
|
||||
deprecated: [
|
||||
{
|
||||
attributes: {
|
||||
text: {
|
||||
type: 'string',
|
||||
default: '随机值',
|
||||
},
|
||||
},
|
||||
|
||||
migrate( { text } ) {
|
||||
return {
|
||||
content: text,
|
||||
};
|
||||
},
|
||||
|
||||
save( props ) {
|
||||
return <p>{ props.attributes.text }</p>;
|
||||
},
|
||||
},
|
||||
],
|
||||
} );
|
||||
```
|
||||
|
||||
在上方示例中,我们将区块的标记从 `p` 更新为 `div`,并将 `text` 属性重命名为 `content`。
|
||||
|
||||
## 修改内部区块
|
||||
|
||||
某些情况下,在迁移区块时可能需要添加或移除内部区块。
|
||||
例如:某个区块需要将标题属性迁移至段落内部区块。
|
||||
|
||||
**示例**
|
||||
|
||||
```js
|
||||
const { registerBlockType } = wp.blocks;
|
||||
|
||||
registerBlockType( 'gutenberg/block-with-deprecated-version', {
|
||||
// ... 区块属性
|
||||
|
||||
save( props ) {
|
||||
return <p>{ props.attributes.title }</p>;
|
||||
},
|
||||
|
||||
deprecated: [
|
||||
{
|
||||
attributes: {
|
||||
title: {
|
||||
type: 'string',
|
||||
source: 'html',
|
||||
selector: 'p',
|
||||
},
|
||||
},
|
||||
|
||||
migrate( attributes, innerBlocks ) {
|
||||
const { title, ...restAttributes } = attributes;
|
||||
|
||||
return [
|
||||
restAttributes,
|
||||
[
|
||||
createBlock( 'core/paragraph', {
|
||||
content: attributes.title,
|
||||
fontSize: 'large',
|
||||
} ),
|
||||
...innerBlocks,
|
||||
],
|
||||
];
|
||||
},
|
||||
|
||||
save( props ) {
|
||||
return <p>{ props.attributes.title }</p>;
|
||||
},
|
||||
},
|
||||
],
|
||||
} );
|
||||
```
|
||||
|
||||
在上方示例中,我们将区块更新为使用带标题的内部段落区块,而非标题属性。
|
||||
|
||||
_以上是区块弃用的示例案例。如需查看真实场景的示例,请参阅[核心区块库](https://github.com/WordPress/gutenberg/tree/HEAD/packages/block-library/src)中的弃用实现。核心区块在版本迭代中持续更新,包含简单与复杂的弃用方案。_
|
||||
|
||||
# 弃用说明
|
||||
|
||||
> 本页面提供了关于弃用API原理与使用的完整指南。入门教程请参阅[开发者博客](https://developer.wordpress.org/news/)上的[区块弃用基础教程](https://developer.wordpress.org/news/2023/03/block-deprecation-a-tutorial/)。
|
||||
|
||||
当更新静态区块标记与属性时,区块开发者需要考虑使用旧版区块的现有文章。为提供平滑的升级路径,您可选择以下策略之一:
|
||||
|
||||
- 不弃用原区块,创建新区块(使用不同名称)
|
||||
- 提供区块的"弃用"版本,允许用户在区块编辑器中打开旧版内容时使用更新后的区块进行编辑。
|
||||
|
||||
一个区块可包含多个弃用版本。当解析后的区块当前状态无效,或弃用版本定义了返回true的`isEligible`函数时,将尝试执行弃用流程。
|
||||
|
||||
弃用机制并非像数据库迁移等软件数据更新那样以链式更新方式运作。初看容易认为每个弃用版本会对数据执行必要修改,然后将新形态的区块传递给下一个弃用版本继续处理。但实际流程是:
|
||||
|
||||
1. 若当前`save`方法无法生成有效区块,弃用数组中的第一个弃用版本将接收原始保存内容
|
||||
2. 若该版本的`save`方法能生成有效内容,则使用此弃用版本来解析区块属性。若其包含`migrate`方法,系统将使用弃用版本解析的属性运行该方法
|
||||
3. 若首个弃用版本的`save`方法无法生成有效区块,则依次尝试数组中后续弃用版本,直到找到能生成有效区块的版本
|
||||
4. 首个生成有效区块的弃用版本对应的属性及innerBlocks,将被传回当前`save`方法以生成新的有效区块内容
|
||||
5. 此时当前区块应处于有效状态,弃用工作流程随即终止
|
||||
|
||||
需特别注意:若弃用版本的`save`方法无法生成有效区块,则其`migrate`方法也会被完全跳过——即使`isEligible`函数对给定属性返回true。这意味着若区块存在多个弃用版本且需执行新迁移(如将内容移至`InnerBlocks`),可能需要更新多个弃用版本中的`migrate`方法,以确保所有历史版本都能应用必要更改。
|
||||
|
||||
另需注意:若弃用版本的`save`方法从其他文件导入额外函数,对这些文件的修改可能意外改变弃用行为。建议将这些函数的快照副本添加到弃用文件中,而非直接导入,以避免意外破坏弃用功能。
|
||||
|
||||
对于含多个弃用版本的区块,建议将每个弃用版本保存为对应区块版本的常量,再将其添加到区块的`deprecated`数组。数组中的弃用版本应按时间倒序排列,这样区块编辑器会优先尝试应用最新且最可能的弃用版本,避免不必要的性能损耗。
|
||||
|
||||
**示例**
|
||||
|
||||
```js
|
||||
const v1 = {};
|
||||
const v2 = {};
|
||||
const v3 = {};
|
||||
const deprecated = [ v3, v2, v1 ];
|
||||
```
|
||||
|
||||
同时建议维护包含不同版本区块内容的[测试固件](https://github.com/WordPress/gutenberg/blob/HEAD/test/integration/fixtures/blocks/README.md),以便轻松验证新弃用版本和迁移功能在所有历史版本中的运行情况。
|
||||
|
||||
弃用定义位于区块类型的`deprecated`属性中,这是一个弃用对象数组,每个对象包含以下形式:
|
||||
|
||||
- `attributes` (对象):区块弃用版本的[属性定义](/docs/reference-guides/block-api/block-attributes.md)
|
||||
- `supports` (对象):区块弃用版本的[支持定义](/docs/reference-guides/block-api/block-registration.md)
|
||||
- `save` (函数):区块弃用版本的[save实现](/docs/reference-guides/block-api/block-edit-save.md)
|
||||
- `migrate`:(函数,可选)。接收旧属性与内部区块后,应返回新属性或与区块兼容的属性元组数组。如前所述,若弃用版本的`save`函数未返回有效区块,其`migrate`将不会运行,因此需确保迁移功能在所有相关弃用版本中均可用。
|
||||
- _参数_
|
||||
- `attributes`: 区块旧属性
|
||||
- `innerBlocks`: 区块旧内部区块
|
||||
- _返回值_
|
||||
- `Object | Array`: 更新后的区块属性或元组数组`[attributes, innerBlocks]`
|
||||
- `isEligible`:(函数,可选)。当函数返回`true`时,即使区块有效仍可由该弃用版本处理迁移。这在区块技术上有效但仍需更新属性或内部区块时特别有用。**注意**:当所有先前弃用版本的save函数结果均无效时,此函数不会被调用。
|
||||
- _参数_
|
||||
- `attributes`: 从序列化HTML解析得到的原始区块属性(在应用区块类型代码之前)
|
||||
- `innerBlocks`: 区块当前内部区块
|
||||
- `data`: 包含代表区块节点及其结果区块对象属性的对象
|
||||
- `data.blockNode`: 解析序列化HTML后得到的区块原始形态
|
||||
- `data.block`: 对`blockNode`应用区块类型后得到的区块对象
|
||||
- _返回值_
|
||||
- `boolean`: 指示此有效区块是否符合该弃用版本的迁移条件
|
||||
|
||||
<div class="callout callout-alert">
|
||||
重要提示:由于<code>attributes</code>、<code>supports</code>和<code>save</code>会影响区块的解析与序列化,它们不会自动从当前版本继承,必须在弃用对象中明确定义才能在迁移过程中被处理。
|
||||
</div>
|
||||
|
||||
**示例**
|
||||
|
||||
```js
|
||||
const { registerBlockType } = wp.blocks;
|
||||
const attributes = {
|
||||
text: {
|
||||
type: 'string',
|
||||
default: 'some random value',
|
||||
},
|
||||
};
|
||||
const supports = {
|
||||
className: false,
|
||||
};
|
||||
|
||||
registerBlockType( 'gutenberg/block-with-deprecated-version', {
|
||||
// ... 其他区块属性
|
||||
|
||||
attributes,
|
||||
|
||||
supports,
|
||||
|
||||
save( props ) {
|
||||
return <div>{ props.attributes.text }</div>;
|
||||
},
|
||||
|
||||
deprecated: [
|
||||
{
|
||||
attributes,
|
||||
|
||||
supports,
|
||||
|
||||
save( props ) {
|
||||
return <p>{ props.attributes.text }</p>;
|
||||
},
|
||||
},
|
||||
],
|
||||
} );
|
||||
```
|
||||
|
||||
以上示例中,我们将区块标记从`p`标签更新为`div`标签。
|
||||
328
reference-guides/block-api/block-edit-save.md
Normal file
328
reference-guides/block-api/block-edit-save.md
Normal file
@@ -0,0 +1,328 @@
|
||||
### 验证常见问题解答
|
||||
|
||||
**区块如何变为无效状态?**
|
||||
|
||||
导致区块失效最常见的两种原因是:
|
||||
|
||||
1. 区块代码存在缺陷,导致内容被意外修改。插件开发者可参阅下文了解如何调试区块失效问题。
|
||||
2. 您或外部编辑器对区块的HTML标记进行了更改,导致其不再符合规范。
|
||||
|
||||
**作为插件开发者,应如何调试区块被标记为无效的问题?**
|
||||
|
||||
开始调试前,请务必先了解上文所述的验证步骤,该步骤记录了检测区块是否无效的流程。当区块重新生成的标记与文章内容中保存的标记不匹配时,该区块即被视为无效,这通常是由于区块属性未能从已保存内容中正确解析所致。
|
||||
|
||||
若您正在使用[属性源](/docs/reference-guides/block-api/block-attributes.md),请确保从标记中提取的属性完全符合预期,且类型正确(通常应为`'字符串'`或`'数字'`类型)。
|
||||
|
||||
当检测到区块无效时,浏览器开发者工具控制台会记录警告信息。该警告会包含标记差异具体位置的详细信息。请仔细比对预期标记与实际标记的差异,定位问题根源。
|
||||
|
||||
**更改区块的`save`行为后,旧内容中出现无效区块应如何修复?**
|
||||
|
||||
请参阅[过时区块处理指南](/docs/reference-guides/block-api/block-deprecation.md),了解如何在主动调整标记时兼容历史内容。
|
||||
|
||||
## 示例
|
||||
|
||||
以下是结合使用属性、编辑和保存功能的几个示例。
|
||||
|
||||
### 将属性保存至子元素
|
||||
|
||||
```jsx
|
||||
attributes: {
|
||||
content: {
|
||||
type: 'string',
|
||||
source: 'html',
|
||||
selector: 'div'
|
||||
}
|
||||
},
|
||||
|
||||
edit: ( { attributes, setAttributes } ) => {
|
||||
const blockProps = useBlockProps();
|
||||
const updateFieldValue = ( val ) => {
|
||||
setAttributes( { content: val } );
|
||||
}
|
||||
return (
|
||||
<div { ...blockProps }>
|
||||
<TextControl
|
||||
__nextHasNoMarginBottom
|
||||
__next40pxDefaultSize
|
||||
label='我的文本字段'
|
||||
value={ attributes.content }
|
||||
onChange={ updateFieldValue }
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
|
||||
save: ( { attributes } ) => {
|
||||
const blockProps = useBlockProps.save();
|
||||
|
||||
return <div { ...blockProps }> { attributes.content } </div>;
|
||||
},
|
||||
```
|
||||
|
||||
### 通过序列化保存属性
|
||||
|
||||
理想情况下,已保存的属性应包含在标记中。但有时这并不现实,因此如果未指定属性来源,该属性会被序列化并保存到块的注释分隔符中。
|
||||
|
||||
此示例适用于动态块(例如[最新文章块](https://github.com/WordPress/gutenberg/blob/HEAD/packages/block-library/src/latest-posts/index.js)),其标记在服务器端渲染。虽然仍需保存函数,但此时仅返回 null,因为该块并不保存编辑器中的内容。
|
||||
|
||||
```jsx
|
||||
attributes: {
|
||||
postsToShow: {
|
||||
type: 'number',
|
||||
}
|
||||
},
|
||||
|
||||
edit: ( { attributes, setAttributes } ) => {
|
||||
const blockProps = useBlockProps();
|
||||
|
||||
return (
|
||||
<div { ...blockProps }>
|
||||
<TextControl
|
||||
__nextHasNoMarginBottom
|
||||
__next40pxDefaultSize
|
||||
label='显示文章数量'
|
||||
value={ attributes.postsToShow }
|
||||
onChange={ ( val ) => {
|
||||
setAttributes( { postsToShow: parseInt( val ) } );
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
|
||||
save: () => {
|
||||
return null;
|
||||
}
|
||||
```
|
||||
|
||||
## 验证
|
||||
|
||||
当编辑器加载时,会对文章内容中的所有块进行验证以确定其准确性,从而防止内容丢失。这与块的保存实现密切相关,因为如果编辑器无法正确恢复块,用户可能会无意中删除或修改其内容。在编辑器初始化期间,使用从文章内容解析出的属性重新生成每个块的已保存标记。如果新生成的标记与文章内容中已存储的标记不匹配,则该块将被标记为无效。这是因为我们假设除非用户进行编辑,否则标记应与已保存内容保持一致。
|
||||
|
||||
如果检测到某个块无效,系统将提示用户选择如何处理无效情况:
|
||||
|
||||

|
||||
|
||||
点击**尝试恢复块**按钮将尽可能执行恢复操作。
|
||||
|
||||
点击块侧边的"三点"菜单会显示三个选项:
|
||||
|
||||
- **解决**:打开解决块对话框,其中包含两个按钮:
|
||||
- **转换为 HTML**:保护已保存文章内容中的原始标记,并将块从其原始类型转换为 HTML 块类型,使用户能够直接修改 HTML 标记。
|
||||
- **转换为块**:保护已保存文章内容中的原始标记,并将块从其原始类型转换为经过验证的块类型。
|
||||
- **转换为 HTML**:保护已保存文章内容中的原始标记,并将块从其原始类型转换为 HTML 块类型,使用户能够直接修改 HTML 标记。
|
||||
- **转换为经典块**:将已保存文章内容中的原始标记视为正确。由于块将从其原始类型转换为经典块类型,因此无法再使用原始块类型的控件来编辑内容。
|
||||
|
||||
## 保存函数
|
||||
|
||||
`save` 函数定义了如何将不同属性组合成最终标记,随后将其序列化到 `post_content` 中。
|
||||
|
||||
```jsx
|
||||
save: () => {
|
||||
const blockProps = useBlockProps.save();
|
||||
|
||||
return <div { ...blockProps }> 您的区块内容 </div>;
|
||||
};
|
||||
```
|
||||
|
||||
对于大多数区块而言,`save` 的返回值应是一个 [WordPress 元素实例](/packages/element/README.md),用于表征区块在前端站点的呈现效果。
|
||||
|
||||
_注意:_ 虽然可以从 `save` 返回字符串值,但该值*会被转义处理*。若字符串包含 HTML 标记,这些标记将在前端站点以字面形式显示,而不会解析为等效的 HTML 节点内容。如必须从 `save` 返回原始 HTML,请使用 `wp.element.RawHTML`。但正如其名所示,这种方式易受[跨站脚本攻击](https://en.wikipedia.org/wiki/Cross-site_scripting),因此建议尽可能使用 WordPress 元素层级结构。
|
||||
|
||||
_注意:_ 保存函数应是纯函数且无状态,仅依赖于调用时传入的属性。它不应使用任何类似 `useState` 或 `useEffect` 的 API,也不应从其他来源获取信息;例如,无法在函数内部使用数据模块 - `select( store ).selector( ... )`。
|
||||
这是因为当外部信息发生变化时,后续编辑文章时可能会导致区块被标记为无效状态([了解更多验证信息](#validation))。
|
||||
|
||||
若需要将其他信息纳入保存过程,开发者可考虑以下两种方案:
|
||||
|
||||
- 使用[动态区块](/docs/how-to-guides/block-tutorial/creating-dynamic-blocks.md)并在服务器端动态获取所需信息
|
||||
- 将外部值存储为属性,并在区块的 `edit` 函数中随变更动态更新
|
||||
|
||||
对于[动态区块](/docs/how-to-guides/block-tutorial/creating-dynamic-blocks.md),`save` 的返回值可表征区块内容的缓存副本,仅当实现区块的插件被禁用时显示。
|
||||
|
||||
若未明确指定,默认实现将不会在文章内容中保存动态区块的标记,而是始终在区块前端显示时实时计算。
|
||||
|
||||
### 区块包装器属性
|
||||
|
||||
与 `edit` 函数类似,在渲染静态区块时,必须将 `useBlockProps.save()` 返回的区块属性添加到区块的包装元素。这能确保区块类名正确渲染,同时包含由区块支持 API 注入的所有 HTML 属性。
|
||||
|
||||
### 属性参数
|
||||
|
||||
与 `edit` 相同,`save` 函数也会接收包含属性的对象参数,这些属性可插入到标记中。
|
||||
|
||||
```jsx
|
||||
save: ( { attributes } ) => {
|
||||
const blockProps = useBlockProps.save();
|
||||
|
||||
return <div { ...blockProps }>{ attributes.content }</div>;
|
||||
};
|
||||
```
|
||||
|
||||
保存区块时,需按照属性源定义规定的相同格式保存属性。若未指定属性源,属性将保存至区块的注释分隔符。详见[区块属性文档](/docs/reference-guides/block-api/block-attributes.md)获取更多信息。
|
||||
|
||||
### 内部区块
|
||||
|
||||
传递给 `save` 函数的参数中还存在第二个属性 `innerBlocks`。该属性通常用于内部操作,实际需要使用的情况极为罕见。
|
||||
|
||||
初始化时,`innerBlocks` 是一个包含嵌套区块对象表征的数组。在极少数需要使用此属性的场景中,它可帮助您调整区块的渲染方式。例如,您可以根据嵌套区块的数量或特定区块类型的存在情况来差异化渲染区块。
|
||||
|
||||
```jsx
|
||||
save: ( { attributes, innerBlocks } ) => {
|
||||
const { className, ...rest } = useBlockProps.save();
|
||||
|
||||
// 初始化期间 innerBlocks 也可能是对象 - React 元素
|
||||
const numberOfInnerBlocks = innerBlocks?.length;
|
||||
if ( numberOfInnerBlocks > 1 ) {
|
||||
className = className + ( className ? ' ' : '' ) + 'more-than-one';
|
||||
};
|
||||
const blockProps = { ...rest, className };
|
||||
|
||||
return <div { ...blockProps }>{ attributes.content }</div>;
|
||||
};
|
||||
```
|
||||
|
||||
此示例中,当内部区块数量超过一个时,会为区块添加额外类名,从而实现区块的差异化样式设计。
|
||||
|
||||
# 编辑与保存
|
||||
|
||||
当在客户端使用 JavaScript 注册区块时,`edit` 和 `save` 函数定义了区块在编辑器中的渲染方式、操作逻辑以及保存机制。
|
||||
|
||||
## 编辑函数
|
||||
|
||||
`edit` 函数描述了区块在编辑器上下文中的结构,决定了编辑器在使用该区块时的渲染内容。
|
||||
|
||||
```jsx
|
||||
import { useBlockProps } from '@wordpress/block-editor';
|
||||
|
||||
// ...
|
||||
const blockSettings = {
|
||||
apiVersion: 3,
|
||||
|
||||
// ...
|
||||
|
||||
edit: () => {
|
||||
const blockProps = useBlockProps();
|
||||
|
||||
return <div { ...blockProps }>您的区块内容</div>;
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
### 区块包装器属性
|
||||
|
||||
首先需要注意的是在区块包装元素上使用的 `useBlockProps` React 钩子。上例中区块包装器在编辑器内渲染为「div」元素,但为了让 Gutenberg 编辑器能够操作区块、添加必要的额外类名...区块包装元素必须应用从 `useBlockProps` React 钩子调用中获取的属性。区块包装元素应是原生 DOM 元素(如 `<div>` 和 `<table>`),或是能将附加属性传递至原生 DOM 元素的 React 组件。而使用 `<Fragment>` 或 `<ServerSideRender>` 等组件则不符合要求。
|
||||
|
||||
若包装元素需要自定义 HTML 属性,需将其作为参数传递给 `useBlockProps` 钩子。例如要为包装器添加 `my-random-classname` 类名:
|
||||
|
||||
```jsx
|
||||
import { useBlockProps } from '@wordpress/block-editor';
|
||||
|
||||
// ...
|
||||
const blockSettings = {
|
||||
apiVersion: 3,
|
||||
|
||||
// ...
|
||||
|
||||
edit: () => {
|
||||
const blockProps = useBlockProps( {
|
||||
className: 'my-random-classname',
|
||||
} );
|
||||
|
||||
return <div { ...blockProps }>您的区块内容</div>;
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
### 属性参数
|
||||
|
||||
`edit` 函数通过对象参数接收多个属性,可用于调整区块行为。
|
||||
|
||||
`attributes` 属性会呈现所有可用属性及其对应值,这些属性在区块类型注册时通过 `attributes` 属性定义(详见[属性文档](/docs/reference-guides/block-api/block-attributes.md))。假设在区块注册时定义了 `content` 属性,即可在编辑函数中调用该值:
|
||||
|
||||
```js
|
||||
edit: ( { attributes } ) => {
|
||||
const blockProps = useBlockProps();
|
||||
|
||||
return <div { ...blockProps }>{ attributes.content }</div>;
|
||||
};
|
||||
```
|
||||
|
||||
当区块插入编辑器时,`attributes.content` 的值将显示在 `div` 中。
|
||||
|
||||
### 选中状态
|
||||
|
||||
isSelected 属性为布尔值,用于标识区块当前是否被选中。
|
||||
|
||||
```jsx
|
||||
edit: ( { attributes, isSelected } ) => {
|
||||
const blockProps = useBlockProps();
|
||||
|
||||
return (
|
||||
<div { ...blockProps }>
|
||||
您的区块内容
|
||||
{ isSelected && (
|
||||
<span>仅当区块被选中时显示</span>
|
||||
) }
|
||||
</div>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
### 属性设置
|
||||
|
||||
setAttributes 函数允许区块根据用户交互更新单个属性。
|
||||
|
||||
```jsx
|
||||
edit: ( { attributes, setAttributes, isSelected } ) => {
|
||||
const blockProps = useBlockProps();
|
||||
|
||||
// 简化属性访问
|
||||
const { content, mySetting } = attributes;
|
||||
|
||||
// 用户点击按钮时切换设置
|
||||
const toggleSetting = () => setAttributes( { mySetting: ! mySetting } );
|
||||
return (
|
||||
<div { ...blockProps }>
|
||||
{ content }
|
||||
{ isSelected && (
|
||||
<button onClick={ toggleSetting }>切换设置</button>
|
||||
) }
|
||||
</div>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
使用对象或数组类型的属性时,建议在更新前先进行复制或克隆:
|
||||
|
||||
```js
|
||||
// 正确做法 - 基于旧列表属性创建新数组并添加新项:
|
||||
const { list } = attributes;
|
||||
const addListItem = ( newListItem ) =>
|
||||
setAttributes( { list: [ ...list, newListItem ] } );
|
||||
|
||||
// 错误做法 - 直接修改现有属性中的列表:
|
||||
const { list } = attributes;
|
||||
const addListItem = ( newListItem ) => {
|
||||
list.push( newListItem );
|
||||
setAttributes( { list } );
|
||||
};
|
||||
```
|
||||
|
||||
这样做的原因在于:JavaScript 中数组和对象通过引用传递,此做法可确保修改不会影响其他持有相同数据引用的代码。此外,Gutenberg 项目遵循 Redux 库的[状态不可变原则](https://redux.js.org/faq/immutable-data#what-are-the-benefits-of-immutability)——不应直接修改数据,而是创建包含变更的新数据版本。
|
||||
|
||||
`setAttribute` 也支持以更新函数作为参数。该函数必须是纯函数,接收当前属性作为唯一参数并返回更新后的属性。此方法适用于需要基于先前状态更新值,或处理对象和数组的场景。
|
||||
|
||||
_**注意:** 自 WordPress 6.9 起支持。_
|
||||
|
||||
```js
|
||||
// 用户点击按钮时切换设置
|
||||
const toggleSetting = () =>
|
||||
setAttributes( ( currentAttr ) => ( {
|
||||
mySetting: ! currentAttr.mySetting,
|
||||
} ) );
|
||||
|
||||
// 向列表添加项目
|
||||
const addListItem = ( newListItem ) =>
|
||||
setAttributes( ( currentAttr ) => ( {
|
||||
list: [ ...currentAttr.list, newListItem ],
|
||||
} ) );
|
||||
```
|
||||
838
reference-guides/block-api/block-metadata.md
Normal file
838
reference-guides/block-api/block-metadata.md
Normal file
@@ -0,0 +1,838 @@
|
||||
### 前端资源加载优化
|
||||
|
||||
自 WordPress 5.8 版本起,开发者可配置仅在前端渲染时加载指定区块类型的脚本与样式。此功能适用于 `block.json` 文件中的以下资源字段:
|
||||
|
||||
- `script`
|
||||
- `viewScript`
|
||||
- `style`
|
||||
- `viewStyle`(WordPress 6.5.0 版本新增)
|
||||
|
||||
## 国际化支持
|
||||
|
||||
WordPress 字符串发现系统可自动翻译本文档中标记为可翻译的字段。首先需在提供区块元数据的 `block.json` 文件中设置 `textdomain` 属性。
|
||||
|
||||
**示例:**
|
||||
|
||||
```json
|
||||
{
|
||||
"title": "我的区块",
|
||||
"description": "我的区块非常出色",
|
||||
"keywords": [ "出色" ],
|
||||
"textdomain": "我的插件"
|
||||
}
|
||||
```
|
||||
|
||||
### PHP 实现
|
||||
|
||||
在 PHP 中,当执行 `register_block_type` 时,本地化属性将在 WordPress 后端自动包裹在 `_x` 函数调用中。这些翻译会以内联脚本形式添加到插件的脚本句柄或 WordPress 核心的 `wp-block-library` 脚本句柄。
|
||||
|
||||
`register_block_type` 处理可翻译值的方式大致等效于以下代码段:
|
||||
|
||||
```php
|
||||
<?php
|
||||
$metadata = array(
|
||||
'title' => _x( '我的区块', '区块标题', '我的插件' ),
|
||||
'description' => _x( '我的区块非常出色!', '区块描述', '我的插件' ),
|
||||
'keywords' => array( _x( '出色', '区块关键词', '我的插件' ) ),
|
||||
);
|
||||
```
|
||||
|
||||
该实现遵循现有的 [get_plugin_data](https://developer.wordpress.org/reference/functions/get_plugin_data) 函数逻辑,通过解析插件内容获取元数据,并动态应用翻译。
|
||||
|
||||
### JavaScript 实现
|
||||
|
||||
在 JavaScript 中,可通过 `@wordpress/blocks` 包的 `registerBlockType` 方法,传入从 `block.json` 加载的元数据对象作为首参数。所有本地化属性会自动包裹在 `_x`(来自 `@wordpress/i18n` 包)函数调用中,其运作机制与 PHP 端类似。
|
||||
|
||||
**示例:**
|
||||
|
||||
```js
|
||||
import { registerBlockType } from '@wordpress/blocks';
|
||||
import Edit from './edit';
|
||||
import metadata from './block.json';
|
||||
|
||||
registerBlockType( metadata, {
|
||||
edit: Edit,
|
||||
// ...其他客户端设置
|
||||
} );
|
||||
```
|
||||
|
||||
## 向后兼容性
|
||||
|
||||
现有注册机制(服务端与前端)将继续生效,它将作为基于 `block.json` 注册方式的底层实现细节。
|
||||
|
||||
待所有细节完善后,核心区块将进行迭代迁移,第三方区块将在控制台中收到警告提示,建议重构现有区块注册 API。
|
||||
|
||||
以下属性将继续在客户端保持向后兼容,部分属性未来可能被替代 API 取代:
|
||||
|
||||
- `edit` - 详见[编辑与保存](/docs/reference-guides/block-api/block-edit-save.md)文档
|
||||
- `save` - 详见[编辑与保存](/docs/reference-guides/block-api/block-edit-save.md)文档
|
||||
- `transforms` - 详见[转换器](/docs/reference-guides/block-api/block-registration.md#transforms-optional)文档
|
||||
- `deprecated` - 详见[废弃区块](/docs/reference-guides/block-api/block-deprecation.md)文档
|
||||
- `merge` - 当前未收录文档,用于处理多区块合并功能
|
||||
- `getEditWrapperProps` - 同样未收录文档,用于向区块编辑组件包装器注入额外属性
|
||||
|
||||
**示例**:
|
||||
|
||||
```js
|
||||
import { registerBlockType } from '@wordpress/blocks';
|
||||
|
||||
registerBlockType( '我的插件/区块名称', {
|
||||
edit: function () {
|
||||
// 编辑定义
|
||||
},
|
||||
save: function () {
|
||||
// 保存定义
|
||||
},
|
||||
getEditWrapperProps: function () {
|
||||
// 实现逻辑
|
||||
},
|
||||
} );
|
||||
```
|
||||
|
||||
对于 WordPress 支持的[动态区块](/docs/how-to-guides/block-tutorial/creating-dynamic-blocks.md),仍可通过服务端的 [`register_block_type`](https://developer.wordpress.org/reference/functions/register_block_type/) 函数注册 `render_callback` 属性。
|
||||
|
||||
# 在 block.json 中定义元数据
|
||||
|
||||
自 WordPress 5.8 版本起,我们建议使用 `block.json` 元数据文件作为通过 PHP(服务端)和 JavaScript(客户端)注册区块类型的标准方式。以下是一个示例 `block.json` 文件,用于为插件创建通知区块定义元数据。
|
||||
|
||||
**示例:**
|
||||
|
||||
```json
|
||||
{
|
||||
"$schema": "https://schemas.wp.org/trunk/block.json",
|
||||
"apiVersion": 3,
|
||||
"name": "my-plugin/notice",
|
||||
"title": "通知",
|
||||
"category": "text",
|
||||
"parent": [ "core/group" ],
|
||||
"icon": "star",
|
||||
"description": "显示警告、错误或成功通知...",
|
||||
"keywords": [ "警示", "消息" ],
|
||||
"version": "1.0.3",
|
||||
"textdomain": "my-plugin",
|
||||
"attributes": {
|
||||
"message": {
|
||||
"type": "string",
|
||||
"source": "html",
|
||||
"selector": ".message"
|
||||
}
|
||||
},
|
||||
"providesContext": {
|
||||
"my-plugin/message": "message"
|
||||
},
|
||||
"usesContext": [ "groupId" ],
|
||||
"selectors": {
|
||||
"root": ".wp-block-my-plugin-notice"
|
||||
},
|
||||
"supports": {
|
||||
"align": true
|
||||
},
|
||||
"styles": [
|
||||
{ "name": "default", "label": "默认", "isDefault": true },
|
||||
{ "name": "other", "label": "其他" }
|
||||
],
|
||||
"example": {
|
||||
"attributes": {
|
||||
"message": "这是一个通知!"
|
||||
}
|
||||
},
|
||||
"variations": [
|
||||
{
|
||||
"name": "example",
|
||||
"title": "示例",
|
||||
"attributes": {
|
||||
"message": "这是一个示例!"
|
||||
}
|
||||
}
|
||||
],
|
||||
"editorScript": "file:./index.js",
|
||||
"script": "file:./script.js",
|
||||
"viewScript": [ "file:./view.js", "example-shared-view-script" ],
|
||||
"editorStyle": "file:./index.css",
|
||||
"style": [ "file:./style.css", "example-shared-style" ],
|
||||
"viewStyle": [ "file:./view.css", "example-view-style" ],
|
||||
"render": "file:./render.php"
|
||||
}
|
||||
```
|
||||
|
||||
## 使用元数据文件的优势
|
||||
|
||||
通过 JSON 格式存储区块类型时,区块定义支持在 JavaScript、PHP 和其他语言之间共享代码。而使用 `block.json` 元数据文件注册区块还能带来额外优势。
|
||||
|
||||
从性能角度来看,当主题支持资源懒加载时,通过 `block.json` 注册的区块将自动实现资源队列优化。在 `style` 或 `script` 属性中列出的前端 CSS 和 JavaScript 资源仅当区块出现在页面上时才会加入队列,从而减小页面体积。
|
||||
|
||||
此外,由于[区块类型 REST API 接口](https://developer.wordpress.org/rest-api/reference/block-types/)仅能列出在服务端注册的区块,因此建议在服务端注册区块;使用 `block.json` 文件可简化此注册过程。
|
||||
|
||||
[WordPress 插件目录](https://wordpress.org/plugins/)能够检测 `block.json` 文件,高亮显示插件中包含的区块,并提取其元数据。若希望将区块提交至区块目录,则插件中包含的所有区块都必须具备 `block.json` 文件,以便区块目录识别它们。
|
||||
|
||||
通过使用预定义的架构描述文件可改善开发体验。支持的编辑器能够提供工具提示、自动补全和架构验证等辅助功能。要使用此架构,请在 `block.json` 文件顶部添加以下内容:
|
||||
|
||||
```json
|
||||
"$schema": "https://schemas.wp.org/trunk/block.json"
|
||||
```
|
||||
|
||||
<div class="callout callout-info">
|
||||
请查阅<a href="https://developer.wordpress.org/block-editor/getting-started/fundamentals-block-development/registration-of-a-block">区块注册文档</a>了解如何使用元数据注册区块。
|
||||
</div>
|
||||
|
||||
## 区块 API
|
||||
|
||||
本节描述所有可添加到 `block.json` 文件中用于定义区块类型行为和元数据的属性。
|
||||
|
||||
### API 版本
|
||||
|
||||
- 类型:`number`
|
||||
- 可选性:可选
|
||||
- 本地化:不支持
|
||||
- 属性:`apiVersion`
|
||||
- 默认值:`1`
|
||||
|
||||
```json
|
||||
{ "apiVersion": 3 }
|
||||
```
|
||||
|
||||
区块所使用的 Block API 版本。最新版本为 `3`,随 WordPress 6.3 引入。
|
||||
|
||||
详见 [API 版本文档](/docs/reference-guides/block-api/block-api-versions.md) 获取更多详细信息。
|
||||
|
||||
### 编辑器脚本
|
||||
|
||||
- 类型:`WPDefinedAsset`|`WPDefinedAsset[]`([了解更多](#wpdefinedasset))
|
||||
- 可选
|
||||
- 是否本地化:否
|
||||
- 属性:`editorScript`
|
||||
|
||||
```json
|
||||
{ "editorScript": "file:./index.js" }
|
||||
```
|
||||
|
||||
区块类型的编辑器脚本定义。这些脚本仅会在编辑器环境中加入队列。
|
||||
|
||||
可以传递使用 [`wp_register_script`](https://developer.wordpress.org/reference/functions/wp_register_script/) 函数注册的脚本句柄、相对于 `block.json` 文件的 JavaScript 文件路径,或包含两者混合的列表([了解更多](#wpdefinedasset))。
|
||||
|
||||
_注意:从 WordPress `6.1.0` 版本开始,支持传递编辑器脚本数组。_
|
||||
|
||||
### 脚本
|
||||
|
||||
- 类型:`WPDefinedAsset`|`WPDefinedAsset[]`([了解更多](#wpdefinedasset))
|
||||
- 可选
|
||||
- 是否本地化:否
|
||||
- 属性:`script`
|
||||
|
||||
```json
|
||||
{ "script": "file:./script.js" }
|
||||
```
|
||||
|
||||
区块类型的前端和编辑器脚本定义。这些脚本会在编辑器环境和网站前端查看内容时同时加入队列。
|
||||
|
||||
可以传递使用 [`wp_register_script`](https://developer.wordpress.org/reference/functions/wp_register_script/) 函数注册的脚本句柄、相对于 `block.json` 文件的 JavaScript 文件路径,或包含两者混合的列表([了解更多](#wpdefinedasset))。
|
||||
|
||||
_注意:从 WordPress `6.1.0` 版本开始,支持传递脚本数组。_
|
||||
|
||||
### 视图脚本
|
||||
|
||||
- 类型:`WPDefinedAsset`|`WPDefinedAsset[]`([了解更多](#wpdefinedasset))
|
||||
- 可选
|
||||
- 是否本地化:否
|
||||
- 属性:`viewScript`
|
||||
- 自:`WordPress 5.9.0`
|
||||
|
||||
```json
|
||||
{ "viewScript": [ "file:./view.js", "example-shared-view-script" ] }
|
||||
```
|
||||
|
||||
区块类型的前端脚本定义。这些脚本仅会在网站前端查看内容时加入队列。
|
||||
|
||||
可以传递使用 [`wp_register_script`](https://developer.wordpress.org/reference/functions/wp_register_script/) 函数注册的脚本句柄、相对于 `block.json` 文件的 JavaScript 文件路径,或包含两者混合的列表([了解更多](#wpdefinedasset))。
|
||||
|
||||
_注意:从 WordPress `6.1.0` 版本开始,支持传递视图脚本数组。_
|
||||
|
||||
### 视图脚本模块
|
||||
|
||||
- 类型:`WPDefinedAsset`|`WPDefinedAsset[]`([了解更多](#wpdefinedasset))
|
||||
- 可选
|
||||
- 是否本地化:否
|
||||
- 属性:`viewScriptModule`
|
||||
- 自:`WordPress 6.5.0`
|
||||
|
||||
```json
|
||||
{ "viewScriptModule": [ "file:./view.js", "example-shared-script-module-id" ] }
|
||||
```
|
||||
|
||||
区块类型的前端脚本模块定义。这些模块仅会在网站前端查看内容时加入队列。
|
||||
|
||||
可以传递使用 [`wp_register_script_module`](https://developer.wordpress.org/reference/functions/wp_register_script_module/) 函数注册的脚本模块 ID、相对于 `block.json` 文件的 JavaScript 模块路径,或包含两者混合的列表([了解更多](#wpdefinedasset))。
|
||||
|
||||
目前 WordPress 脚本与 WordPress 脚本模块不兼容。如果前端视图资源依赖于 WordPress 脚本,应使用 `viewScript`;如果依赖于 WordPress 脚本模块(当前为交互性 API),则应使用 `viewScriptModule`。脚本模块的[更多功能](https://core.trac.wordpress.org/ticket/60647)将逐步开放。
|
||||
|
||||
_注意:此功能自 WordPress `6.5.0` 版本起可用。_
|
||||
|
||||
### 编辑器样式
|
||||
|
||||
- 类型:`WPDefinedAsset`|`WPDefinedAsset[]`([了解更多](#wpdefinedasset))
|
||||
- 可选
|
||||
- 是否本地化:否
|
||||
- 属性:`editorStyle`
|
||||
|
||||
```json
|
||||
{ "editorStyle": "file:./index.css" }
|
||||
```
|
||||
|
||||
区块类型的编辑器样式定义。这些样式仅会在编辑器环境中加入队列。
|
||||
|
||||
可以传递使用 [`wp_register_style`](https://developer.wordpress.org/reference/functions/wp_register_style/) 函数注册的样式句柄、相对于 `block.json` 文件的 CSS 文件路径,或包含两者混合的列表([了解更多](#wpdefinedasset))。
|
||||
|
||||
_注意:从 WordPress `5.9.0` 版本开始,支持传递编辑器样式数组。_
|
||||
|
||||
### 名称
|
||||
|
||||
- 类型:`字符串`
|
||||
- 必需
|
||||
- 是否本地化:否
|
||||
- 属性:`name`
|
||||
|
||||
```json
|
||||
{ "name": "core/heading" }
|
||||
```
|
||||
|
||||
区块名称是用于标识区块的唯一字符串。名称必须遵循 `命名空间/区块名称` 的结构,其中命名空间是插件或主题的名称。
|
||||
|
||||
**注意:** 区块名称只能包含小写字母数字字符、连字符,且最多只能包含一个正斜杠用于表示插件唯一的命名空间前缀。名称必须以字母开头。
|
||||
|
||||
**注意:** 此名称在注释分隔符中使用,格式为 `<!-- wp:my-plugin/book -->`。属于 `core` 命名空间的区块类型在序列化时不包含命名空间。
|
||||
|
||||
### 标题
|
||||
|
||||
- 类型:`字符串`
|
||||
- 必需
|
||||
- 是否本地化:是
|
||||
- 属性:`title`
|
||||
|
||||
```json
|
||||
{ "title": "标题" }
|
||||
```
|
||||
|
||||
这是区块的显示标题,可以通过翻译函数进行翻译。标题将显示在插入器及编辑器的其他区域中。
|
||||
|
||||
**注意:** 为了确保区块标题在用户界面中易于阅读和访问,请尽量避免使用过长的标题。
|
||||
|
||||
### 分类
|
||||
|
||||
- 类型:`字符串`
|
||||
- 可选
|
||||
- 是否本地化:否
|
||||
- 属性:`category`
|
||||
|
||||
```json
|
||||
{ "category": "文本" }
|
||||
```
|
||||
|
||||
区块按分类进行分组,以帮助用户浏览和发现它们。
|
||||
|
||||
核心提供的分类包括:
|
||||
|
||||
- 文本
|
||||
- 媒体
|
||||
- 设计
|
||||
- 小工具
|
||||
- 主题
|
||||
- 嵌入
|
||||
|
||||
插件和主题还可以注册[自定义区块分类](/docs/reference-guides/filters/block-filters.md#managing-block-categories)。
|
||||
|
||||
实现应预期并容忍未知分类,并提供合理的回退行为(例如使用“文本”分类)。
|
||||
|
||||
### 父级
|
||||
|
||||
- 类型:`字符串数组`
|
||||
- 可选
|
||||
- 是否本地化:否
|
||||
- 属性:`parent`
|
||||
|
||||
```json
|
||||
{ "parent": [ "my-block/product" ] }
|
||||
```
|
||||
|
||||
设置 `parent` 可以让一个区块仅在嵌套于指定区块内时才可用。例如,可以允许“加入购物车”区块仅在“产品”区块内可用。
|
||||
|
||||
### 祖先
|
||||
|
||||
- 类型:`字符串数组`
|
||||
- 可选
|
||||
- 是否本地化:否
|
||||
- 属性:`ancestor`
|
||||
- 自:`WordPress 6.0.0`
|
||||
|
||||
```json
|
||||
{ "ancestor": [ "my-block/product" ] }
|
||||
```
|
||||
|
||||
`ancestor` 属性使区块可以在指定区块类型的子树中的任何位置使用。例如,可以在“列”区块中放置“评论内容”区块,只要“列”区块位于“评论模板”区块的子树中。与 `parent` 属性相比,指定了 `ancestor` 的区块可以放置在子树的任何位置,而指定了 `parent` 的区块必须是直接子级。
|
||||
|
||||
### 允许的区块
|
||||
|
||||
- 类型:`字符串数组`
|
||||
- 可选
|
||||
- 是否本地化:否
|
||||
- 属性:`allowedBlocks`
|
||||
- 自:`WordPress 6.5.0`
|
||||
|
||||
```json
|
||||
{ "allowedBlocks": [ "my-block/product" ] }
|
||||
```
|
||||
|
||||
`allowedBlocks` 指定哪些区块类型可以作为该区块的直接子级。例如,“列表”区块可以仅允许“列表项”区块作为子级。
|
||||
|
||||
### 图标
|
||||
|
||||
- 类型:`字符串`
|
||||
- 可选
|
||||
- 是否本地化:否
|
||||
- 属性:`icon`
|
||||
|
||||
```json
|
||||
{ "icon": "smile" }
|
||||
```
|
||||
|
||||
应指定图标属性以便更容易识别区块。图标可以是 [WordPress 的 Dashicons](https://developer.wordpress.org/resource/dashicons/) 中的任意图标(在非 JavaScript 环境中,图标别名也可作为回退)。
|
||||
|
||||
**注意:** 也可以通过客户端使用 SVG 元素的源来覆盖此属性。此外,此属性可以通过 JavaScript 定义为包含背景色和前景色的对象。这些颜色将在适用时与图标一起显示,例如在插入器中。自定义 SVG 图标会自动包装在 [wp.primitives.SVG](/packages/primitives/README.md) 组件中,以添加可访问性属性(aria-hidden、role 和 focusable)。
|
||||
|
||||
### 描述
|
||||
|
||||
- 类型:`字符串`
|
||||
- 可选
|
||||
- 是否本地化:是
|
||||
- 属性:`description`
|
||||
|
||||
```json
|
||||
{
|
||||
"description": "引入新板块并组织内容,以帮助访客更好地浏览"
|
||||
}
|
||||
```
|
||||
|
||||
这是区块的简短描述,可以通过翻译函数进行翻译。此描述将显示在区块检查器中。
|
||||
|
||||
### 关键词
|
||||
|
||||
- 类型:`string[]`
|
||||
- 可选
|
||||
- 支持本地化:是
|
||||
- 属性:`keywords`
|
||||
- 默认值:`[]`
|
||||
|
||||
```json
|
||||
{ "keywords": [ "keyword1", "keyword2" ] }
|
||||
```
|
||||
|
||||
有时,一个区块可以设置别名,帮助用户在搜索时发现它。例如,图片区块可能还希望通过“照片”一词被搜索到。您可以通过提供不限数量的术语数组(这些术语会被翻译)来实现此功能。
|
||||
|
||||
### 版本
|
||||
|
||||
- 类型:`string`
|
||||
- 可选
|
||||
- 支持本地化:否
|
||||
- 属性:`version`
|
||||
- 自:`WordPress 5.8.0`
|
||||
|
||||
```json
|
||||
{ "version": "1.0.3" }
|
||||
```
|
||||
|
||||
区块的当前版本号,例如 1.0 或 1.0.3。这与插件版本管理类似。此字段可能与区块资源一起用于控制缓存失效,如果区块作者未提供此字段,则使用已安装的 WordPress 版本号代替。
|
||||
|
||||
### 文本域
|
||||
|
||||
- 类型:`string`
|
||||
- 可选
|
||||
- 支持本地化:否
|
||||
- 属性:`textdomain`
|
||||
- 自:`WordPress 5.7.0`
|
||||
|
||||
```json
|
||||
{ "textdomain": "my-plugin" }
|
||||
```
|
||||
|
||||
插件/区块的 [gettext](https://www.gnu.org/software/gettext/) 文本域。更多信息请参见[如何国际化您的插件](https://developer.wordpress.org/plugins/internationalization/how-to-internationalize-your-plugin/)页面中的[文本域](https://developer.wordpress.org/plugins/internationalization/how-to-internationalize-your-plugin/#text-domains)部分。
|
||||
|
||||
### 属性
|
||||
|
||||
- 类型:`object`
|
||||
- 可选
|
||||
- 支持本地化:否
|
||||
- 属性:`attributes`
|
||||
- 默认值:`{}`
|
||||
|
||||
```json
|
||||
{
|
||||
"attributes": {
|
||||
"cover": {
|
||||
"type": "string",
|
||||
"source": "attribute",
|
||||
"selector": "img",
|
||||
"attribute": "src"
|
||||
},
|
||||
"author": {
|
||||
"type": "string",
|
||||
"source": "html",
|
||||
"selector": ".book-author"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
属性提供了区块的结构化数据需求。它们在序列化时可以以不同形式存在,但在通用接口下统一声明。
|
||||
|
||||
更多详情请参阅[属性文档](/docs/reference-guides/block-api/block-attributes.md)。
|
||||
|
||||
### 提供上下文
|
||||
|
||||
- 类型:`object`
|
||||
- 可选
|
||||
- 支持本地化:否
|
||||
- 属性:`providesContext`
|
||||
- 默认值:`{}`
|
||||
|
||||
以对象形式提供上下文,将上下文名称映射到区块自身的某个属性,供该类型区块的子级访问。
|
||||
|
||||
更多详情请参阅[区块上下文文档](/docs/reference-guides/block-api/block-context.md)。
|
||||
|
||||
```json
|
||||
{
|
||||
"providesContext": {
|
||||
"my-plugin/recordId": "recordId"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 上下文
|
||||
|
||||
- 类型:`string[]`
|
||||
- 可选
|
||||
- 支持本地化:否
|
||||
- 属性:`usesContext`
|
||||
- 默认值:`[]`
|
||||
|
||||
要从祖先提供者继承的上下文值名称数组。
|
||||
|
||||
更多详情请参阅[区块上下文文档](/docs/reference-guides/block-api/block-context.md)。
|
||||
|
||||
```json
|
||||
{
|
||||
"usesContext": [ "message" ]
|
||||
}
|
||||
```
|
||||
|
||||
### 选择器
|
||||
|
||||
- 类型:`object`
|
||||
- 可选
|
||||
- 支持本地化:否
|
||||
- 属性:`selectors`
|
||||
- 默认值:`{}`
|
||||
- 自:`WordPress 6.3.0`
|
||||
|
||||
在生成 theme.json(全局样式)样式表的区块样式时使用的任何自定义 CSS 选择器,按 `root`、功能或子功能作为键。提供自定义选择器可以更精细地控制样式应用于哪些区块元素,例如,仅将排版样式应用于内部标题,而颜色样式仍应用于外部区块包装器等。
|
||||
|
||||
更多详情请参阅[选择器文档](/docs/reference-guides/block-api/block-selectors.md)。
|
||||
|
||||
```json
|
||||
{
|
||||
"selectors": {
|
||||
"root": ".my-custom-block-selector",
|
||||
"color": {
|
||||
"text": ".my-custom-block-selector p"
|
||||
},
|
||||
"typography": {
|
||||
"root": ".my-custom-block-selector > h2",
|
||||
"text-decoration": ".my-custom-block-selector > h2 span"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 支持功能
|
||||
|
||||
- 类型:`object`
|
||||
- 可选
|
||||
- 支持本地化:否
|
||||
- 属性:`supports`
|
||||
- 默认值:`{}`
|
||||
|
||||
包含一组用于控制编辑器中使用的功能的选项。更多详情请参阅[支持功能文档](/docs/reference-guides/block-api/block-supports.md)。
|
||||
|
||||
### 区块样式
|
||||
|
||||
- 类型:`数组`
|
||||
- 可选
|
||||
- 支持本地化:是(仅限 `label` 字段)
|
||||
- 属性:`styles`
|
||||
- 默认值:`[]`
|
||||
|
||||
```json
|
||||
{
|
||||
"styles": [
|
||||
{ "name": "default", "label": "默认", "isDefault": true },
|
||||
{ "name": "other", "label": "其他" }
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
区块样式可用于为区块提供替代样式,其实现原理是通过在区块包装器上添加类名。主题开发者可以利用 CSS 针对已选定的区块样式类名进行样式定制。
|
||||
|
||||
插件和主题还可以为现有区块注册[自定义区块样式](/docs/reference-guides/block-api/block-styles.md)。
|
||||
|
||||
### 示例配置
|
||||
|
||||
- 类型:`对象`
|
||||
- 可选
|
||||
- 支持本地化:否
|
||||
- 属性:`example`
|
||||
|
||||
```json
|
||||
{
|
||||
"example": {
|
||||
"attributes": {
|
||||
"message": "这是一个通知!"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
该配置用于为区块提供结构化的示例数据。当用户将鼠标悬停在区块上时,这些数据将用于在检查器帮助面板中构建区块预览效果。
|
||||
|
||||
更多详细信息请参阅[示例配置文档](/docs/reference-guides/block-api/block-registration.md#example-optional)。
|
||||
|
||||
### 区块变体
|
||||
|
||||
- 类型:`对象数组|WP预定义路径`([了解更多](#wpdefinedpath))
|
||||
- 可选
|
||||
- 支持本地化:是(仅限各变体的 `title`、`description` 和 `keywords` 字段)
|
||||
- 属性:`variations`
|
||||
- 版本要求:`WordPress 5.9.0` 及以上
|
||||
|
||||
```json
|
||||
{
|
||||
"variations": [
|
||||
{
|
||||
"name": "example",
|
||||
"title": "示例",
|
||||
"attributes": {
|
||||
"level": 2,
|
||||
"message": "这是一个示例!"
|
||||
},
|
||||
"scope": [ "block" ],
|
||||
"isActive": [ "level" ]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
区块变体 API 允许一个区块拥有多个相似版本,这些版本共享某些通用功能。每个区块变体通过设置不同的初始属性或内部区块来相互区分。当插入区块时,这些属性和/或内部区块会被自动应用。
|
||||
|
||||
*注意:在 JavaScript 中可为 `isActive` 属性提供函数,为 `icon` 属性提供 React 元素。而在 `block.json` 文件中,这两个属性仅支持字符串类型*
|
||||
|
||||
从 6.7 版本开始,可以在 `block.json` 中指定一个 PHP 文件来在服务端生成区块变体列表:
|
||||
|
||||
```json
|
||||
{ "variations": "file:./variations.php" }
|
||||
```
|
||||
|
||||
该 PHP 文件需要返回包含区块变体的数组。从 PHP 文件返回的变体中的字符串不会自动本地化,需照常使用 `__()` 函数进行处理。
|
||||
|
||||
例如:
|
||||
|
||||
```php
|
||||
<?php
|
||||
// 为社交图标类区块生成变体
|
||||
|
||||
return array(
|
||||
array(
|
||||
'isDefault' => true,
|
||||
'name' => 'wordpress',
|
||||
'title' => 'WordPress',
|
||||
'icon' => 'wordpress',
|
||||
'attributes' => array(
|
||||
'service' => 'wordpress',
|
||||
),
|
||||
'isActive' => array( 'service' )
|
||||
),
|
||||
array(
|
||||
'name' => 'mail',
|
||||
'title' => __( '邮件' ),
|
||||
'keywords' => array(
|
||||
__( '邮箱' ),
|
||||
__( '电子邮件' )
|
||||
),
|
||||
'icon' => 'mail',
|
||||
'attributes' => array(
|
||||
'service' => 'mail',
|
||||
),
|
||||
'isActive' => array( 'mail' )
|
||||
),
|
||||
);
|
||||
|
||||
```
|
||||
|
||||
更多详细信息请参阅[变体文档](/docs/reference-guides/block-api/block-variations.md)。
|
||||
|
||||
### 区块钩子
|
||||
|
||||
- 类型:`对象`
|
||||
- 可选
|
||||
- 属性:`blockHooks`
|
||||
- 版本要求:`WordPress 6.4.0` 及以上
|
||||
|
||||
```json
|
||||
{
|
||||
"blockHooks": {
|
||||
"my-plugin/banner": "after"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
区块钩子 API 允许区块自动插入到指定区块类型的所有实例旁,其相对位置也由被"挂钩"的区块指定。即区块可以选择插入到指定区块类型的前后,或作为其首个子区块/最后一个子区块(即分别在其子区块列表的开头或末尾添加)。被挂钩的区块将同时在前端和编辑器中显示(以便用户进行自定义)。
|
||||
|
||||
配置中的键是要挂钩的区块名称(`字符串`),值是要挂钩的位置(`字符串`)。请参阅[区块钩子文档](/docs/reference-guides/block-api/block-registration.md#block-hooks-optional)了解更多可用配置信息。
|
||||
|
||||
### 样式
|
||||
|
||||
- 类型:`WPDefinedAsset` | `WPDefinedAsset[]`([了解更多](#wpdefinedasset))
|
||||
- 可选
|
||||
- 是否本地化:否
|
||||
- 属性:`style`
|
||||
|
||||
```json
|
||||
{ "style": [ "file:./style.css", "example-shared-style" ] }
|
||||
```
|
||||
|
||||
区块类型的前端和编辑器样式定义。这些样式将在编辑器和前端查看内容时同时加载。
|
||||
|
||||
可以传递通过 [`wp_register_style`](https://developer.wordpress.org/reference/functions/wp_register_style/) 函数注册的样式句柄、相对于 `block.json` 文件的 CSS 文件路径,或包含两者的混合列表([了解更多](#wpdefinedasset))。
|
||||
|
||||
*注意:从 WordPress `5.9.0` 版本开始,支持传递样式数组。*
|
||||
|
||||
### 查看样式
|
||||
|
||||
- 类型:`WPDefinedAsset` | `WPDefinedAsset[]`([了解更多](#wpdefinedasset))
|
||||
- 可选
|
||||
- 是否本地化:否
|
||||
- 属性:`viewStyle`
|
||||
- 自版本:`WordPress 6.5.0`
|
||||
|
||||
```json
|
||||
{ "viewStyle": [ "file:./view.css", "example-view-style" ] }
|
||||
```
|
||||
|
||||
区块类型的前端样式定义。这些样式仅在前端查看内容时加载。
|
||||
|
||||
可以传递通过 [`wp_register_style`](https://developer.wordpress.org/reference/functions/wp_register_style/) 函数注册的样式句柄、相对于 `block.json` 文件的 CSS 文件路径,或包含两者的混合列表([了解更多](#wpdefinedasset))。
|
||||
|
||||
仅前端样式特别适用于交互式区块,用于样式化仅在用户执行某些操作后可见的部分,且这些样式在编辑器中永远不需要。你可以先使用 `style` 属性将所有通用样式放在一个样式表中。仅当需要特定于编辑器的样式或特定于前端的样式时,可以扩展使用 `editorStyle` 和 `viewStyle`,但仍将样式的主要通用部分保留在主样式表中。
|
||||
|
||||
### 渲染
|
||||
|
||||
- 类型:`WPDefinedPath`([了解更多](#wpdefinedpath))
|
||||
- 可选
|
||||
- 是否本地化:否
|
||||
- 属性:`render`
|
||||
- 自版本:`WordPress 6.1.0`
|
||||
|
||||
```json
|
||||
{ "render": "file:./render.php" }
|
||||
```
|
||||
|
||||
在服务器上渲染区块类型以在前端显示时使用的 PHP 文件。该文件暴露以下变量:
|
||||
|
||||
- `$attributes`(`array`):区块属性。
|
||||
- `$content`(`string`):区块默认内容。
|
||||
- `$block`(`WP_Block`):区块实例。
|
||||
|
||||
使用 `render` 定义的 `render.php` 文件的示例实现可能如下:
|
||||
|
||||
```php
|
||||
<div <?php echo get_block_wrapper_attributes(); ?>>
|
||||
<?php echo esc_html( $attributes['label'] ); ?>
|
||||
</div>
|
||||
```
|
||||
|
||||
*注意:在服务器上渲染页面 HTML 时,此文件会为每个区块类型的实例加载。在文件中声明函数或类时,必须考虑到这一点。避免错误风险的最简单方法是从另一个文件调用共享逻辑。*
|
||||
|
||||
## 资源
|
||||
|
||||
### `WPDefinedPath`
|
||||
|
||||
`WPDefinedPath` 类型是字符串的子类型,其值表示相对于 `block.json` 文件位置的 JavaScript、CSS 或 PHP 文件路径。提供的路径必须以 `file:` 为前缀。此方法基于 npm 处理包的[本地路径](https://docs.npmjs.com/files/package.json#local-paths)的方式。
|
||||
|
||||
**示例:**
|
||||
|
||||
在 `block.json` 中:
|
||||
|
||||
```json
|
||||
{
|
||||
"render": "file:./render.php"
|
||||
}
|
||||
```
|
||||
|
||||
### `WPDefinedAsset`
|
||||
|
||||
它扩展了 `WPDefinedPath`,适用于 JavaScript 和 CSS 文件。文件路径的替代方案可以是脚本句柄、脚本模块 ID 或样式句柄,引用使用 WordPress 辅助函数已注册的资源。
|
||||
|
||||
**示例:**
|
||||
|
||||
在 `block.json` 中:
|
||||
|
||||
```json
|
||||
{
|
||||
"editorScript": "file:./index.js",
|
||||
"script": "file:./script.js",
|
||||
"viewScriptModule": [
|
||||
"file:./view.js",
|
||||
"example-registered-script-module-id"
|
||||
],
|
||||
"editorStyle": "file:./index.css",
|
||||
"style": [ "file:./style.css", "example-shared-style" ],
|
||||
"viewStyle": [ "file:./view.css", "example-view-style" ]
|
||||
}
|
||||
```
|
||||
|
||||
在 WordPress 环境中,当使用 PHP 注册区块时,它将自动注册在 `block.json` 文件中找到的所有脚本、脚本模块和样式,并使用文件路径而非资源句柄。
|
||||
|
||||
这就是为什么 `WPDefinedAsset` 类型必须提供一种方式来镜像使用 [`wp_register_script`](https://developer.wordpress.org/reference/functions/wp_register_script/)、[`wp_register_script_module`](https://developer.wordpress.org/reference/functions/wp_register_script_module/) 和 [`wp_register_style`](https://developer.wordpress.org/reference/functions/wp_register_style/) 注册脚本、脚本模块和样式所需的参数,然后将这些参数作为与区块关联的句柄或脚本模块 ID。
|
||||
|
||||
可以提供具有以下结构的对象:
|
||||
|
||||
- `handle`(`string`)- 脚本的名称。如果省略,将自动生成。
|
||||
- `dependencies`(`string[]` | `{ id: string, import?: 'dynamic'|'static' }[]`)- 此脚本依赖的已注册脚本句柄数组。脚本模块可以使用简单字符串表示静态依赖项,或使用对象形式表示动态依赖项。动态依赖项是可能在运行时使用或不使用的依赖项,通常与动态 `import('module-id')` 语法一起使用。默认值:`[]`。
|
||||
- `version`(`string` | `false` | `null`)- 指定脚本版本号的字符串(如果有),将作为查询字符串添加到 URL 中以实现缓存清除。如果版本设置为 `false`,则自动添加等于当前安装的 WordPress 版本的版本号。如果设置为 `null`,则不添加版本。默认值:`false`。
|
||||
|
||||
该定义存储在一个单独的 PHP 文件中,该文件以 `.asset.php` 结尾,并位于 `block.json` 中列出的 JS/CSS 文件旁边。WordPress 将通过模式匹配自动检测此文件。此选项是首选,因为预计它将与 `@wordpress/scripts` 包一起自动生成这些资源文件。
|
||||
|
||||
**示例:**
|
||||
|
||||
```
|
||||
build/
|
||||
├─ block.json
|
||||
├─ index.js
|
||||
└─ index.asset.php
|
||||
```
|
||||
|
||||
在 `block.json` 中:
|
||||
|
||||
```json
|
||||
{ "editorScript": "file:./index.js" }
|
||||
```
|
||||
|
||||
在 `build/index.asset.php` 中:
|
||||
|
||||
```php
|
||||
<?php
|
||||
return array(
|
||||
'dependencies' => array(
|
||||
'react',
|
||||
'wp-blocks',
|
||||
'wp-i18n',
|
||||
),
|
||||
'version' => '3be55b05081a63d8f9d0ecb466c42cfd',
|
||||
);
|
||||
```
|
||||
206
reference-guides/block-api/block-patterns.md
Normal file
206
reference-guides/block-api/block-patterns.md
Normal file
@@ -0,0 +1,206 @@
|
||||
## 语义化区块模式
|
||||
|
||||
在区块主题中,您还可以将区块模式标记为"页眉"或"页脚"模式(模板部件区域)。我们称之为"语义化区块模式"。当用户插入或替换页眉/页脚模板部件时,这些模式将会显示给用户。
|
||||
|
||||
示例:
|
||||
|
||||
```php
|
||||
<?php
|
||||
register_block_pattern(
|
||||
'my-plugin/my-header',
|
||||
array(
|
||||
'title' => __( '我的页眉', 'my-plugin' ),
|
||||
'categories' => array( 'header' ),
|
||||
// 将该模式指定至"header"区域
|
||||
'blockTypes' => array( 'core/template-part/header' ),
|
||||
'content' => '我的区块模式内容',
|
||||
)
|
||||
);
|
||||
```
|
||||
|
||||
# 区块模式
|
||||
|
||||
区块模式是从区块插入器的模式选项卡中可用的预定义区块布局。一旦插入到内容中,这些区块即可用于添加或修改内容及配置。
|
||||
|
||||
## 区块模式
|
||||
|
||||
### register_block_pattern
|
||||
|
||||
编辑器自带若干核心区块模式。主题和插件作者可以使用 `register_block_pattern` 辅助函数来注册额外的自定义区块模式。
|
||||
|
||||
`register_block_pattern` 辅助函数接收两个参数:
|
||||
- `title`:一个遵循 `命名空间/标题` 命名约定的机器可读标题。
|
||||
- `properties`:描述模式属性的数组。
|
||||
|
||||
区块模式可用的属性包括:
|
||||
|
||||
- `title`(必需):模式的人类可读标题。
|
||||
- `content`(必需):模式的区块 HTML 标记。
|
||||
- `description`(可选):在插入器中用于描述模式的视觉隐藏文本。描述是可选的,但当标题未能完全说明模式功能时,强烈建议提供。描述将帮助用户在搜索时发现该模式。
|
||||
- `categories`(可选):用于对区块模式进行分组的已注册模式类别数组。区块模式可显示在多个类别中。类别必须单独注册才能在此处使用。
|
||||
- `keywords`(可选):帮助用户在搜索时发现模式的别名或关键词数组。
|
||||
- `viewportWidth`(可选):指定模式预期宽度的整数,以便在插入器中显示模式的缩放预览。
|
||||
- `blockTypes`(可选):模式预期与之配合使用的区块类型数组。每个值需为已声明区块的 `name`。
|
||||
- `postTypes`(可选):模式限制与之配合使用的文章类型数组。该模式仅在编辑数组中传递的某一文章类型时可用。对于所有其他文章类型,该模式完全不可用。
|
||||
- `templateTypes`(可选):模式适用的模板类型数组,例如,如果模式用于 404 页面,则为 `404`;如果模式用于显示单篇文章,则为 `single-post`。
|
||||
- `inserter`(可选):默认情况下,所有模式都会出现在插入器中。若要隐藏模式,使其只能通过编程方式插入,请将 `inserter` 设置为 `false`。
|
||||
- `source`(可选):表示模式来源的字符串。对于注册模式的插件,传递字符串 `plugin`;对于主题,传递字符串 `theme`。
|
||||
|
||||
以下代码示例注册了一个名为 `my-plugin/my-awesome-pattern` 的区块模式:
|
||||
|
||||
```php
|
||||
register_block_pattern(
|
||||
'my-plugin/my-awesome-pattern',
|
||||
array(
|
||||
'title' => __( '两个按钮', 'my-plugin' ),
|
||||
'description' => _x( '两个水平按钮,左侧按钮为实心填充,右侧按钮为轮廓样式。', '区块模式描述', 'my-plugin' ),
|
||||
'content' => "<!-- wp:buttons {\"align\":\"center\"} -->\n<div class=\"wp-block-buttons aligncenter\"><!-- wp:button {\"backgroundColor\":\"very-dark-gray\",\"borderRadius\":0} -->\n<div class=\"wp-block-button\"><a class=\"wp-block-button__link has-background has-very-dark-gray-background-color no-border-radius\">" . esc_html__( '按钮一', 'my-plugin' ) . "</a></div>\n<!-- /wp:button -->\n\n<!-- wp:button {\"textColor\":\"very-dark-gray\",\"borderRadius\":0,\"className\":\"is-style-outline\"} -->\n<div class=\"wp-block-button is-style-outline\"><a class=\"wp-block-button__link has-text-color has-very-dark-gray-color no-border-radius\">" . esc_html__( '按钮二', 'my-plugin' ) . "</a></div>\n<!-- /wp:button --></div>\n<!-- /wp:buttons -->",
|
||||
)
|
||||
);
|
||||
```
|
||||
|
||||
请注意,`register_block_pattern()` 应从附加到 `init` 钩子的处理程序中调用。
|
||||
|
||||
```php
|
||||
function my_plugin_register_my_patterns() {
|
||||
register_block_pattern( ... );
|
||||
}
|
||||
|
||||
add_action( 'init', 'my_plugin_register_my_patterns' );
|
||||
```
|
||||
|
||||
## 取消注册区块模式
|
||||
|
||||
### unregister_block_pattern
|
||||
|
||||
`unregister_block_pattern` 辅助函数允许从主题或插件中取消注册先前已注册的区块模式,它接收一个参数。
|
||||
|
||||
- `title`:要取消注册的区块模式的名称。
|
||||
|
||||
以下代码示例取消了名为 `my-plugin/my-awesome-pattern` 的区块模式的注册:
|
||||
|
||||
```php
|
||||
unregister_block_pattern( 'my-plugin/my-awesome-pattern' );
|
||||
```
|
||||
|
||||
_注意:_
|
||||
|
||||
`unregister_block_pattern()` 应在附加到 init 钩子的处理程序中调用。
|
||||
|
||||
```php
|
||||
function my_plugin_unregister_my_patterns() {
|
||||
unregister_block_pattern( ... );
|
||||
}
|
||||
|
||||
add_action( 'init', 'my_plugin_unregister_my_patterns' );
|
||||
```
|
||||
|
||||
## 区块模式分类
|
||||
|
||||
区块模式可以使用分类进行分组。区块编辑器自带了一些捆绑的分类,您可以在自定义区块模式中使用。您也可以注册自己的区块模式分类。
|
||||
|
||||
### register_block_pattern_category
|
||||
|
||||
`register_block_pattern_category` 辅助函数接收两个参数。
|
||||
|
||||
- `title`:区块模式分类的机器可读标题。
|
||||
- `properties`:描述模式分类属性的数组。
|
||||
|
||||
模式分类的属性包括:
|
||||
|
||||
- `label`(必需):模式分类的人类可读标签。
|
||||
|
||||
以下代码示例注册了名为 `hero` 的分类:
|
||||
|
||||
```php
|
||||
register_block_pattern_category(
|
||||
'hero',
|
||||
array( 'label' => __( 'Hero', 'my-plugin' ) )
|
||||
);
|
||||
```
|
||||
|
||||
_注意:_
|
||||
|
||||
`register_block_pattern_category()` 应在附加到 init 钩子的处理程序中调用。
|
||||
|
||||
除非有模式被分配到此分类,否则该分类不会显示在“模式”下。
|
||||
|
||||
```php
|
||||
function my_plugin_register_my_pattern_categories() {
|
||||
register_block_pattern_category( ... );
|
||||
}
|
||||
|
||||
add_action( 'init', 'my_plugin_register_my_pattern_categories' );
|
||||
```
|
||||
|
||||
### unregister_block_pattern_category
|
||||
|
||||
`unregister_block_pattern_category` 辅助函数允许从主题或插件中取消注册先前已注册的区块模式分类,它接收一个参数。
|
||||
|
||||
- `title`:要取消注册的区块模式分类的名称。
|
||||
|
||||
以下代码示例取消了名为 `hero` 的分类的注册:
|
||||
|
||||
```php
|
||||
unregister_block_pattern_category( 'hero' );
|
||||
```
|
||||
|
||||
_注意:_
|
||||
|
||||
`unregister_block_pattern_category()` 应在附加到 init 钩子的处理程序中调用。
|
||||
|
||||
```php
|
||||
function my_plugin_unregister_my_pattern_categories() {
|
||||
unregister_block_pattern_category( ... );
|
||||
}
|
||||
|
||||
add_action( 'init', 'my_plugin_unregister_my_pattern_categories' );
|
||||
```
|
||||
|
||||
## 特定于区块类型的区块模式和模式转换
|
||||
|
||||
可以将一个区块模式附加到一个或多个区块类型。这会将该区块模式添加为该区块类型的可用转换。
|
||||
|
||||
目前,这些转换仅适用于简单区块(没有内部块的区块)。为了建议某个模式,**所选中的每个块都必须存在于该区块模式中**。
|
||||
|
||||
例如:
|
||||
|
||||
```php
|
||||
register_block_pattern(
|
||||
'my-plugin/powered-by-wordpress',
|
||||
array(
|
||||
'title' => __( 'Powered by WordPress', 'my-plugin' ),
|
||||
'blockTypes' => array( 'core/paragraph' ),
|
||||
'content' => '<!-- wp:paragraph {"backgroundColor":"black","textColor":"white"} -->
|
||||
<p class="has-white-color has-black-background-color has-text-color has-background">Powered by WordPress</p>
|
||||
<!-- /wp:paragraph -->',
|
||||
)
|
||||
);
|
||||
```
|
||||
|
||||
上面的代码注册了一个名为 `my-plugin/powered-by-wordpress` 的区块模式,并在段落块的“转换菜单”中显示该模式。转换结果将保留段落的现有内容并应用其他属性——在本例中为背景色和文本颜色。
|
||||
|
||||
如上所述,如果我们选择了多个块,并且存在与这些块匹配的上下文模式,那么简单区块的模式转换也可以工作。让我们看一个附加了两个区块类型的模式示例。
|
||||
|
||||
```php
|
||||
register_block_pattern(
|
||||
'my-plugin/powered-by-wordpress',
|
||||
array(
|
||||
'title' => __( 'Powered by WordPress', 'my-plugin' ),
|
||||
'blockTypes' => array( 'core/paragraph', 'core/heading' ),
|
||||
'content' => '<!-- wp:group -->
|
||||
<div class="wp-block-group">
|
||||
<!-- wp:heading {"fontSize":"large"} -->
|
||||
<h2 class="has-large-font-size"><span style="color:#ba0c49" class="has-inline-color">Hi everyone</span></h2>
|
||||
<!-- /wp:heading -->
|
||||
<!-- wp:paragraph {"backgroundColor":"black","textColor":"white"} -->
|
||||
<p class="has-white-color has-black-background-color has-text-color has-background">Powered by WordPress</p>
|
||||
<!-- /wp:paragraph -->
|
||||
</div><!-- /wp:group -->',
|
||||
)
|
||||
);
|
||||
```
|
||||
|
||||
在上面的示例中,如果我们选择**两个区块类型中的任意一个**,无论是段落块还是标题块,此模式都将通过转换所选块的内容来建议,并且还会添加模式中剩余的块。另一方面,如果我们多选一个段落块和一个标题块,则这两个块都将被转换。
|
||||
|
||||
区块也可以在其他地方使用这些上下文区块模式。例如,当插入新的查询循环块时,会向用户提供附加到该块的所有模式的列表。
|
||||
371
reference-guides/block-api/block-registration.md
Normal file
371
reference-guides/block-api/block-registration.md
Normal file
@@ -0,0 +1,371 @@
|
||||
## 区块集合
|
||||
|
||||
## `registerBlockCollection`
|
||||
|
||||
- **类型:** `函数`
|
||||
|
||||
区块可被添加至集合中,将同一来源的所有区块归组管理。
|
||||
|
||||
`registerBlockCollection` 接收两个参数:`namespace` 和一个包含 `title` 与 `icon` 的设置对象。
|
||||
|
||||
### 命名空间
|
||||
|
||||
- **类型:** `字符串`
|
||||
|
||||
此命名空间需与区块名称中声明的命名空间一致;即您的插件或主题的名称。
|
||||
|
||||
### 设置
|
||||
|
||||
#### 标题
|
||||
|
||||
- **类型:** `字符串`
|
||||
|
||||
此标题将在区块插入器的部分显示,列出此集合中的所有区块。
|
||||
|
||||
#### 图标
|
||||
|
||||
- **类型:** `对象`
|
||||
|
||||
(可选)在区块插入器中与标题一同显示的图标。
|
||||
|
||||
```js
|
||||
// 注册一个区块集合
|
||||
registerBlockCollection( 'my-plugin', { title: '我的插件' } );
|
||||
```
|
||||
|
||||
# 注册
|
||||
|
||||
区块注册 API 参考文档。
|
||||
|
||||
<div class="callout callout-alert">
|
||||
您可以使用本文档记录的函数仅在客户端通过 JavaScript 注册区块,但推荐的方式是同时使用服务端的 PHP 通过 `block.json` 元数据文件注册新区块类型。请参阅<a href="https://developer.wordpress.org/block-editor/reference-guides/block-api/block-metadata/">元数据文档获取完整信息</a>
|
||||
<br/>
|
||||
<a href="https://developer.wordpress.org/block-editor/getting-started/create-block/">了解如何创建您的第一个区块</a>。从搭建开发环境、熟悉工具到适应新的开发模式,本教程涵盖了开始创建区块所需掌握的所有知识。
|
||||
</div>
|
||||
|
||||
## `registerBlockType`
|
||||
|
||||
- **类型:** `函数`
|
||||
|
||||
每个区块都从注册新的区块类型定义开始。要注册区块,您需要使用 [`wp-blocks` 包](/packages/blocks/README.md#registerBlockType) 中的 `registerBlockType` 函数。该函数接收两个参数:区块 `name` 和区块配置对象。
|
||||
|
||||
### 区块名称
|
||||
|
||||
- **类型:** `字符串`
|
||||
|
||||
区块名称是用于标识区块的唯一字符串。名称必须采用 `命名空间/区块名称` 的结构,其中命名空间是您的插件或主题名称。
|
||||
|
||||
```js
|
||||
// 使用唯一名称注册我的区块
|
||||
registerBlockType( 'my-plugin/book', {} );
|
||||
```
|
||||
|
||||
_注意:_ 区块名称只能包含小写字母数字字符和连字符,且必须以字母开头。
|
||||
|
||||
_注意:_ 此名称在注释分隔符中使用,格式为 `<!-- wp:my-plugin/book -->`。核心提供的区块在序列化时不包含命名空间。
|
||||
|
||||
#### 重要提示:请谨慎选择命名空间
|
||||
|
||||
区块名称一旦确定后续将无法随意更改。区块名称会存储在使用该区块的每篇文章的内容中,因此更改名称需要编辑所有受影响的文章或运行数据库脚本。
|
||||
|
||||
#### 命名空间最佳实践
|
||||
|
||||
- 使用实际的插件/主题名称:`my-awesome-plugin/block-name`
|
||||
- 避免使用通用名称,如 `editorial/`、`block/` 或 `create-block/`
|
||||
- 为插件/主题中的所有区块使用相同的命名空间
|
||||
- 确保命名空间唯一性,防止与其他插件冲突
|
||||
|
||||
```js
|
||||
// 优秀示例
|
||||
registerBlockType( 'my-company-blocks/hero', {} );
|
||||
registerBlockType( 'awesome-gallery-plugin/slideshow', {} );
|
||||
|
||||
// 避免以下示例
|
||||
registerBlockType( 'create-block/example', {} ); // 过于通用
|
||||
registerBlockType( 'block/content', {} ); // 过于通用
|
||||
```
|
||||
|
||||
_注意:_ `registerBlockCollection()` 仅适用于单一命名空间下的区块。
|
||||
|
||||
### 区块配置
|
||||
|
||||
- **类型:** `对象` [ `{ 键: 值 }` ]
|
||||
|
||||
区块需要指定若干属性才能成功注册。这些属性通过配置对象定义,包含以下内容:
|
||||
|
||||
#### title
|
||||
|
||||
- **类型:** `字符串`
|
||||
|
||||
这是区块的显示标题,可通过翻译函数进行本地化。标题将显示在插入器及编辑器的其他区域。
|
||||
|
||||
```js
|
||||
// 数据对象示例
|
||||
title: __( '书籍' );
|
||||
```
|
||||
|
||||
_注意:_ 为确保区块标题在界面中易于阅读和访问,请尽量避免使用过长的标题。
|
||||
|
||||
#### description(可选)
|
||||
|
||||
- **类型:** `字符串`
|
||||
|
||||
这是区块的简短描述,可通过翻译函数进行本地化。该描述将显示在设置侧边栏的区块选项卡中。
|
||||
|
||||
```js
|
||||
description: __( '显示书籍卡片的区块。' );
|
||||
```
|
||||
|
||||
#### category
|
||||
|
||||
- **类型:** `字符串` [ text | media | design | widgets | theme | embed ]
|
||||
|
||||
区块按类别分组,以帮助用户浏览和发现。
|
||||
|
||||
核心提供的类别包括:
|
||||
|
||||
- text(文本)
|
||||
- media(媒体)
|
||||
- design(设计)
|
||||
- widgets(小工具)
|
||||
- theme(主题)
|
||||
- embed(嵌入)
|
||||
|
||||
```js
|
||||
// 分配到 'widgets' 类别
|
||||
category: 'widgets',
|
||||
```
|
||||
|
||||
插件和主题也可以注册[自定义区块类别](/docs/reference-guides/filters/block-filters.md#managing-block-categories)。
|
||||
|
||||
#### variations(可选)
|
||||
|
||||
- **类型:** `Object[]`
|
||||
- **始于:** `WordPress 5.9.0`
|
||||
|
||||
与声明块样式的方式类似,块类型可以定义用户可供选择的块变体。不同之处在于,此字段不仅改变视觉外观,还提供在插入块时应用初始自定义属性和内部块的方法。更多详情请参阅[块变体 API](/docs/reference-guides/block-api/block-variations.md)。
|
||||
|
||||
#### supports(可选)
|
||||
|
||||
- **类型:** `Object`
|
||||
|
||||
`supports` 包含一组用于控制编辑器中使用的功能的选项。更多详情请参阅 [`supports` 文档](/docs/reference-guides/block-api/block-supports.md)。
|
||||
|
||||
#### transforms(可选)
|
||||
|
||||
- **类型:** `Object`
|
||||
|
||||
`transforms` 提供了块可以从哪些内容转换而来以及可以转换为哪些内容的规则。块可以从另一个块、短代码、正则表达式、文件或原始 DOM 节点转换而来。有关每个可用转换的更多信息,请参阅[块转换 API](/docs/reference-guides/block-api/block-transforms.md)。
|
||||
|
||||
#### parent(可选)
|
||||
|
||||
- **类型:** `Array`
|
||||
|
||||
块可以插入到使用 [`InnerBlocks`](https://github.com/WordPress/gutenberg/blob/HEAD/packages/block-editor/src/components/inner-blocks/README.md) 作为嵌套内容的块中。有时,限制块仅作为嵌套块可用是有用的。例如,您可能希望仅允许“加入购物车”块在“产品”块内使用。
|
||||
|
||||
设置 `parent` 可以让块要求仅在嵌套在指定块中时才可用。
|
||||
|
||||
```js
|
||||
// 仅允许此块嵌套在 Columns 块中
|
||||
parent: [ 'core/columns' ],
|
||||
```
|
||||
|
||||
#### ancestor(可选)
|
||||
|
||||
- **类型:** `Array`
|
||||
- **始于:** `WordPress 6.0.0`
|
||||
|
||||
`ancestor` 属性使块可以在指定块类型的子树中的任何位置使用。例如,只要“列”块位于“评论模板”块内的某个位置,就可以将“评论内容”块放置在“列”块中。与 `parent` 属性相比,指定了 `ancestor` 的块可以放置在子树的任何位置,而指定了 `parent` 的块必须是直接子级。
|
||||
|
||||
```js
|
||||
// 仅允许此块在 Columns 块的任意层级中嵌套
|
||||
ancestor: [ 'core/columns' ],
|
||||
```
|
||||
|
||||
#### allowedBlocks(可选)
|
||||
|
||||
- **类型:** `Array`
|
||||
- **始于:** `WordPress 6.5.0`
|
||||
|
||||
设置 `allowedBlocks` 属性将限制哪些块类型可以作为该块的直接子级嵌套。
|
||||
|
||||
```js
|
||||
// 仅允许 Columns 块作为此块的直接子级嵌套
|
||||
allowedBlocks: [ 'core/columns' ],
|
||||
```
|
||||
|
||||
#### blockHooks(可选)
|
||||
|
||||
- **类型:** `Object`
|
||||
- **始于:** `WordPress 6.4.0`
|
||||
|
||||
块钩子是一个 API,允许块自动插入到给定块类型的所有实例旁边,其相对位置也由“被钩入”的块指定。也就是说,块可以选择插入到给定块类型之前或之后,或者作为其第一个或最后一个子级(即分别在其子块列表的开头或末尾添加)。被钩入的块将同时显示在前端和编辑器中(以允许用户进行自定义)。
|
||||
|
||||
键是要钩入的块的名称(`string`),值是要钩入的位置(`string`)。允许的目标值包括:
|
||||
|
||||
- `before` – 在目标块之前注入。
|
||||
- `after` – 在目标块之后注入。
|
||||
- `firstChild` – 在目标容器块的第一个内部块之前注入。
|
||||
- `lastChild` – 在目标容器块的最后一个内部块之后注入。
|
||||
|
||||
```js
|
||||
{
|
||||
blockHooks: {
|
||||
'core/verse': 'before',
|
||||
'core/spacer': 'after',
|
||||
'core/column': 'firstChild',
|
||||
'core/group': 'lastChild',
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 图标(可选)
|
||||
|
||||
- **类型:** `字符串` | `对象`
|
||||
|
||||
应指定图标属性以便更轻松地识别区块。图标可以是任意 [WordPress Dashicon](https://developer.wordpress.org/resource/dashicons/),或自定义的 `svg` 元素。
|
||||
|
||||
```js
|
||||
// 为区块指定 Dashicon
|
||||
icon: 'book-alt',
|
||||
|
||||
// 为区块指定自定义 SVG
|
||||
icon: <svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path fill="none" d="M0 0h24v24H0V0z" /><path d="M19 13H5v-2h14v2z" /></svg>,
|
||||
```
|
||||
|
||||
**注意:** 自定义 SVG 图标会自动包裹在 [`wp.primitives.SVG` 组件](/packages/primitives/README.md) 中,以添加可访问性属性(`aria-hidden`、`role` 和 `focusable`)。
|
||||
|
||||
也可以将对象作为图标传递,此时,如上所述的图标应包含在 `src` 属性中。
|
||||
|
||||
除了 `src`,对象还可以包含背景色和前景色,这些颜色将在适用时与图标一起显示,例如:在插入器中。
|
||||
|
||||
```js
|
||||
icon: {
|
||||
// 指定与图标一起显示的背景色,例如:在插入器中。
|
||||
background: '#7e70af',
|
||||
// 指定图标颜色(可选:如果未设置,将自动定义易读的颜色)
|
||||
foreground: '#fff',
|
||||
// 为区块指定图标
|
||||
src: <svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path fill="none" d="M0 0h24v24H0V0z" /><path d="M19 13H5v-2h14v2z" /></svg>,
|
||||
} ,
|
||||
```
|
||||
|
||||
#### 关键词(可选)
|
||||
|
||||
- **类型:** `数组`
|
||||
|
||||
有时,区块可能有别名,以帮助用户在搜索时发现它。例如,`image` 区块可能也希望通过 `photo` 被发现。您可以通过提供一组术语(可翻译)来实现。
|
||||
|
||||
```js
|
||||
// 通过关键词别名更轻松地发现区块。
|
||||
// 这些关键词可以本地化,因此您的关键词可以在不同语言环境中使用。
|
||||
keywords: [ __( 'image' ), __( 'photo' ), __( 'pics' ) ],
|
||||
```
|
||||
|
||||
#### 样式(可选)
|
||||
|
||||
- **类型:** `数组`
|
||||
|
||||
区块样式可用于为区块提供替代样式。它通过向区块包装器添加类名来实现。使用 CSS,主题开发者可以在选中区块样式时定位该类名。
|
||||
|
||||
```js
|
||||
// 注册区块样式。
|
||||
styles: [
|
||||
// 将样式标记为默认。
|
||||
{
|
||||
name: 'default',
|
||||
label: __( 'Rounded' ),
|
||||
isDefault: true
|
||||
},
|
||||
{
|
||||
name: 'outline',
|
||||
label: __( 'Outline' )
|
||||
},
|
||||
{
|
||||
name: 'squared',
|
||||
label: __( 'Squared' )
|
||||
},
|
||||
],
|
||||
```
|
||||
|
||||
插件和主题还可以为现有区块注册 [自定义区块样式](/docs/reference-guides/block-api/block-styles.md)。
|
||||
|
||||
#### 属性(可选)
|
||||
|
||||
- **类型:** `对象`
|
||||
|
||||
属性提供了区块所需的结构化数据。它们在序列化时可以以不同形式存在,但它们在通用接口下一起声明。
|
||||
|
||||
```js
|
||||
// 指定区块属性
|
||||
attributes: {
|
||||
cover: {
|
||||
type: 'string',
|
||||
source: 'attribute',
|
||||
selector: 'img',
|
||||
attribute: 'src',
|
||||
},
|
||||
author: {
|
||||
type: 'string',
|
||||
source: 'html',
|
||||
selector: '.book-author',
|
||||
},
|
||||
pages: {
|
||||
type: 'number',
|
||||
},
|
||||
},
|
||||
```
|
||||
|
||||
- **参见:[属性](/docs/reference-guides/block-api/block-attributes.md)。**
|
||||
|
||||
#### 示例(可选)
|
||||
|
||||
- **类型:** `对象`
|
||||
|
||||
示例为区块提供了结构化的示例数据。这些数据用于构建区块的预览,当用户将鼠标悬停在区块上时,预览将显示在检查器帮助面板中;当选中区块时,预览将显示在样式面板中。
|
||||
|
||||
示例对象中提供的数据应与定义的属性匹配。例如:
|
||||
|
||||
```js
|
||||
example: {
|
||||
attributes: {
|
||||
cover: 'https://example.com/image.jpg',
|
||||
author: 'William Shakespeare',
|
||||
pages: 500
|
||||
},
|
||||
},
|
||||
```
|
||||
|
||||
如果未定义 `example`,则不会显示预览。因此,即使未定义任何属性,设置空的示例对象 `example: {}` 也会触发预览显示。
|
||||
|
||||
还可以通过 `innerBlocks` 使用内部区块扩展区块预览。例如:
|
||||
|
||||
```js
|
||||
example: {
|
||||
attributes: {
|
||||
cover: 'https://example.com/image.jpg',
|
||||
},
|
||||
innerBlocks: [
|
||||
{
|
||||
name: 'core/paragraph',
|
||||
attributes: {
|
||||
/* 翻译示例文本。 */
|
||||
content: __(
|
||||
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent et eros eu felis.'
|
||||
),
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
```
|
||||
|
||||
还可以通过 `viewportWidth` 以像素为单位定义预览容器的宽度。例如:
|
||||
|
||||
```js
|
||||
example: {
|
||||
attributes: {
|
||||
cover: 'https://example.com/image.jpg',
|
||||
},
|
||||
viewportWidth: 800
|
||||
},
|
||||
```
|
||||
97
reference-guides/block-api/block-selectors.md
Normal file
97
reference-guides/block-api/block-selectors.md
Normal file
@@ -0,0 +1,97 @@
|
||||
# 选择器
|
||||
|
||||
区块选择器是允许区块自定义生成样式时使用的 CSS 选择器的 API。
|
||||
|
||||
区块可在三个层级自定义其 CSS 选择器:根级、功能级和子功能级。
|
||||
|
||||
## 根选择器
|
||||
|
||||
根选择器是区块的主 CSS 选择器。
|
||||
|
||||
所有区块都需要一个主 CSS 选择器来包含其样式声明。如果未通过区块选择器 API 提供,将默认生成格式为 `.wp-block-<名称>` 的选择器。
|
||||
|
||||
### 示例
|
||||
|
||||
```json
|
||||
{
|
||||
...
|
||||
"selectors": {
|
||||
"root": ".my-custom-block-selector"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 功能选择器
|
||||
|
||||
功能选择器关联区块支持的样式,例如边框、颜色、排版等。
|
||||
|
||||
区块可能希望将特定功能的样式应用到区块内的不同元素。例如在区块包装器上使用颜色样式,但仅将排版样式应用到内部标题。
|
||||
|
||||
### 示例
|
||||
|
||||
```json
|
||||
{
|
||||
...
|
||||
"selectors": {
|
||||
"root": ".my-custom-block-selector",
|
||||
"color": ".my-custom-block-selector",
|
||||
"typography": ".my-custom-block-selector > h2"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 子功能选择器
|
||||
|
||||
这些选择器关联区块支持提供的独立样式,例如 `background-color`。
|
||||
|
||||
子功能可以在其独有的选择器下生成样式。当某个区块支持子功能无法与应用了该支持其他子功能的元素相同时,这尤其有用。
|
||||
|
||||
`text-decoration` 就是一个很好的例子。网页浏览器对此样式的渲染方式不同,如果将其添加到包装元素,则很难被覆盖。通过为 `text-decoration` 分配自定义选择器,其样式可以仅定位到应应用的元素。
|
||||
|
||||
### 示例
|
||||
|
||||
```json
|
||||
{
|
||||
...
|
||||
"selectors": {
|
||||
"root": ".my-custom-block-selector",
|
||||
"color": ".my-custom-block-selector",
|
||||
"typography": {
|
||||
"root": ".my-custom-block-selector > h2",
|
||||
"text-decoration": ".my-custom-block-selector > h2 span"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 简写形式
|
||||
|
||||
您可以为相关功能设置单个选择器作为字符串值,而不必为每个子功能指定 CSS 选择器。这是上文示例中 `color` 功能所演示的方法。
|
||||
|
||||
## 回退机制
|
||||
|
||||
未针对特定功能配置的选择器将回退到区块的根选择器。类似地,如果子功能未设置自定义选择器,它将回退到其父功能的选择器,如果父功能选择器也不可用,将进一步回退到区块的根选择器。
|
||||
|
||||
您可以将通用选择器设置为父功能的 `root` 选择器,并仅为不同的子功能定义独特选择器,而不必为多个子功能重复设置选择器。
|
||||
|
||||
### 示例
|
||||
|
||||
```json
|
||||
{
|
||||
...
|
||||
"selectors": {
|
||||
"root": ".my-custom-block-selector",
|
||||
"color": {
|
||||
"text": ".my-custom-block-selector p"
|
||||
},
|
||||
"typography": {
|
||||
"root": ".my-custom-block-selector > h2",
|
||||
"text-decoration": ".my-custom-block-selector > h2 span"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
在上面的示例中,`color.background-color` 子功能未显式设置。由于 `color` 功能也未定义 `root` 选择器,`color.background-color` 将被包含在区块的主根选择器 `.my-custom-block-selector` 下。
|
||||
|
||||
对于诸如 `typography.font-size` 的子功能,由于存在父功能选择器,它将回退到父功能的选择器,即 `.my-custom-block-selector > h2`。
|
||||
142
reference-guides/block-api/block-styles.md
Normal file
142
reference-guides/block-api/block-styles.md
Normal file
@@ -0,0 +1,142 @@
|
||||
# 样式
|
||||
|
||||
区块样式允许为现有区块应用替代样式。其实现原理是向区块包装器添加 className。当用户选中某个区块样式时,该 className 可用于为区块提供替代样式。关于如何为区块应用样式的完整示例,请参阅[使用样式和样式表](/docs/how-to-guides/block-tutorial/applying-styles-with-stylesheets.md)。
|
||||
|
||||
_示例:_
|
||||
|
||||
```js
|
||||
wp.blocks.registerBlockStyle( 'core/quote', {
|
||||
name: 'fancy-quote',
|
||||
label: '花式引用',
|
||||
} );
|
||||
```
|
||||
|
||||
以上示例为 `core/quote` 区块注册了名为 `fancy-quote` 的区块样式。当用户从样式选择器中选中此区块样式时,区块包装器将添加 `is-style-fancy-quote` 的 className。
|
||||
|
||||
通过设置 `isDefault: true`,可将注册的区块样式标记为未提供自定义类名时的默认激活样式。这也意味着标记为默认的样式不会在 HTML 输出中添加自定义类名。
|
||||
|
||||
如需移除区块样式,请使用 `wp.blocks.unregisterBlockStyle()`。
|
||||
|
||||
_示例:_
|
||||
|
||||
```js
|
||||
wp.blocks.unregisterBlockStyle( 'core/quote', 'large' );
|
||||
```
|
||||
|
||||
以上代码将从 `core/quote` 区块中移除名为 `large` 的区块样式。
|
||||
|
||||
**重要提示:** 在取消注册区块样式时,可能存在[竞态条件](https://en.wikipedia.org/wiki/Race_condition)——注册样式和取消注册样式的代码执行顺序不确定。为确保取消注册代码最后执行,需将注册样式的组件(本例中为 `wp-edit-post`)指定为依赖项。此外,使用 `wp.domReady()` 可确保取消注册代码在 DOM 加载完成后执行。
|
||||
|
||||
通过以下 PHP 代码加载你的 JavaScript:
|
||||
|
||||
```php
|
||||
function myguten_enqueue() {
|
||||
wp_enqueue_script(
|
||||
'myguten-script',
|
||||
plugins_url( 'myguten.js', __FILE__ ),
|
||||
array( 'wp-blocks', 'wp-dom-ready', 'wp-edit-post' ),
|
||||
filemtime( plugin_dir_path( __FILE__ ) . '/myguten.js' )
|
||||
);
|
||||
}
|
||||
add_action( 'enqueue_block_editor_assets', 'myguten_enqueue' );
|
||||
```
|
||||
|
||||
`myguten.js` 中的 JavaScript 代码:
|
||||
|
||||
```js
|
||||
wp.domReady( function () {
|
||||
wp.blocks.unregisterBlockStyle( 'core/quote', 'large' );
|
||||
} );
|
||||
```
|
||||
|
||||
## 服务端注册辅助函数
|
||||
|
||||
虽然提供的示例能完全控制区块样式,但需要编写大量代码。
|
||||
|
||||
为简化注册和取消注册区块样式的流程,还提供了两个服务端函数:`register_block_style` 和 `unregister_block_style`。
|
||||
|
||||
### register_block_style
|
||||
|
||||
`register_block_style` 函数的第一个参数接收区块名称,第二个参数接收描述样式属性的数组。
|
||||
|
||||
样式数组的属性必须包含 `name` 和 `label`:
|
||||
|
||||
- `name`:用于计算 CSS 类的样式标识符
|
||||
- `label`:用户可读的样式标签
|
||||
|
||||
除了这两个必需属性外,样式属性数组还应包含 `inline_style`、`style_handle` 或 `style_data` 属性之一:
|
||||
|
||||
- `inline_style`:包含注册样式所需 CSS 类的内联 CSS 代码
|
||||
- `style_handle`:包含已注册样式句柄,该样式将在需要区块样式的地方被加载
|
||||
- `style_data`:包含 theme.json 风格的样式属性数组(自 WordPress 6.6 起可用)
|
||||
|
||||
还可以将 `is_default` 属性设置为 `true`,将某个区块样式标记为默认样式。
|
||||
|
||||
以下代码示例为引用区块注册名为“蓝色引用”的样式,并提供内联样式使采用“蓝色引用”样式的引用区块显示为蓝色:
|
||||
|
||||
```php
|
||||
register_block_style(
|
||||
'core/quote',
|
||||
array(
|
||||
'name' => 'blue-quote',
|
||||
'label' => __( '蓝色引用', 'textdomain' ),
|
||||
'inline_style' => '.wp-block-quote.is-style-blue-quote { color: blue; }',
|
||||
)
|
||||
);
|
||||
```
|
||||
|
||||
如果已注册包含区块样式 CSS 的样式表,只需传递样式表句柄,`register_block_style` 函数将确保其被加载:
|
||||
|
||||
```php
|
||||
wp_register_style( 'myguten-style', get_template_directory_uri() . '/custom-style.css' );
|
||||
|
||||
// ...
|
||||
|
||||
register_block_style(
|
||||
'core/quote',
|
||||
array(
|
||||
'name' => 'fancy-quote',
|
||||
'label' => __( '花式引用', 'textdomain' ),
|
||||
'style_handle' => 'myguten-style',
|
||||
)
|
||||
);
|
||||
```
|
||||
|
||||
另一种方式是使用 `style_data` 属性(如下例),为图片区块添加带橙色边框和微圆角的样式:
|
||||
|
||||
```php
|
||||
register_block_style(
|
||||
array( 'core/image' ),
|
||||
array(
|
||||
'name' => 'orange-border',
|
||||
'label' => __( '橙色边框', 'pauli' ),
|
||||
'style_data'=> array(
|
||||
'border' => array(
|
||||
'color' => '#f5bc42',
|
||||
'style' => 'solid',
|
||||
'width' => '4px',
|
||||
'radius' => '15px'
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
```
|
||||
|
||||
使用 `style_data` 属性允许用户通过**编辑器 > 样式**中的全局样式界面进行修改。该属性自 WordPress 6.6 版本开始提供。
|
||||
|
||||
更多信息请参阅 WordPress 6.6 开发说明:[区块样式章节](https://make.wordpress.org/core/2024/06/24/section-styles/)。
|
||||
另见 WordPress 开发者博客:[在 WordPress 6.6 中使用区块样式变体为区块区域、嵌套元素等设置样式](https://developer.wordpress.org/news/2024/06/styling-sections-nested-elements-and-more-with-block-style-variations-in-wordpress-6-6/)。
|
||||
|
||||
### unregister_block_style
|
||||
|
||||
`unregister_block_style` 用于取消注册之前通过 `register_block_style` 在服务端注册的区块样式。
|
||||
|
||||
函数的第一个参数是区块的注册名称,第二个参数是样式名称。
|
||||
|
||||
以下代码示例从引用区块中取消注册名为 'fancy-quote' 的样式:
|
||||
|
||||
```php
|
||||
unregister_block_style( 'core/quote', 'fancy-quote' );
|
||||
```
|
||||
|
||||
**重要说明:** `unregister_block_style` 函数仅取消注册通过 `register_block_style` 在服务端注册的样式,不会取消注册通过客户端代码注册的样式。
|
||||
1166
reference-guides/block-api/block-supports.md
Normal file
1166
reference-guides/block-api/block-supports.md
Normal file
File diff suppressed because it is too large
Load Diff
184
reference-guides/block-api/block-templates.md
Normal file
184
reference-guides/block-api/block-templates.md
Normal file
@@ -0,0 +1,184 @@
|
||||
# 模板
|
||||
|
||||
区块模板被定义为一组区块项目的列表。这类区块可以包含预定义的属性、占位符内容,并且可以是静态或动态的。区块模板允许为编辑器会话指定默认的初始状态。
|
||||
|
||||
模板的适用范围包括:
|
||||
|
||||
- 在客户端动态设置默认状态(例如 `defaultBlock`)
|
||||
- 注册为特定文章类型的默认模板
|
||||
|
||||
计划新增功能:
|
||||
|
||||
- 保存并作为“页面模板”分配给页面
|
||||
- 在 `template.php` 文件中定义,或从站点特定的自定义文章类型(`wp_templates`)中拉取
|
||||
- 作为主题层级的等效方案
|
||||
|
||||
## API
|
||||
|
||||
模板可以在 JS 或 PHP 中声明为一个 blockTypes 数组(区块名称和可选属性)。
|
||||
|
||||
以下第一个 PHP 示例为文章创建了一个包含图片区块的模板,您可以根据需要向模板中添加任意数量的区块。
|
||||
|
||||
PHP 示例:
|
||||
|
||||
```php
|
||||
<?php
|
||||
function myplugin_register_template() {
|
||||
$post_type_object = get_post_type_object( 'post' );
|
||||
$post_type_object->template = array(
|
||||
array( 'core/image' ),
|
||||
);
|
||||
}
|
||||
add_action( 'init', 'myplugin_register_template' );
|
||||
```
|
||||
|
||||
以下 JavaScript 示例使用 [InnerBlocks](https://github.com/WordPress/gutenberg/blob/HEAD/packages/block-editor/src/components/inner-blocks/README.md) 和模板创建了一个新区块,插入时会基于模板生成一组区块。
|
||||
|
||||
```js
|
||||
const el = React.createElement;
|
||||
const { registerBlockType } = wp.blocks;
|
||||
const { InnerBlocks } = wp.blockEditor;
|
||||
|
||||
const BLOCKS_TEMPLATE = [
|
||||
[ 'core/image', {} ],
|
||||
[ 'core/paragraph', { placeholder: '图片详情' } ],
|
||||
];
|
||||
|
||||
registerBlockType( 'myplugin/template', {
|
||||
title: '我的模板区块',
|
||||
category: 'widgets',
|
||||
edit: ( props ) => {
|
||||
return el( InnerBlocks, {
|
||||
template: BLOCKS_TEMPLATE,
|
||||
templateLock: false,
|
||||
} );
|
||||
},
|
||||
save: ( props ) => {
|
||||
return el( InnerBlocks.Content, {} );
|
||||
},
|
||||
} );
|
||||
```
|
||||
|
||||
有关实际使用模板的完整示例,请参阅 [元区块教程](/docs/how-to-guides/metabox.md#step-4-finishing-touches)。
|
||||
|
||||
## 区块属性
|
||||
|
||||
要查找可在模板中定义的所有区块属性的完整列表,请查阅区块的 `block.json` 文件,并查看 `attributes` 和 `supports` 值。
|
||||
|
||||
例如,[packages/block-library/src/heading/block.json](https://github.com/WordPress/gutenberg/blob/c62ccd80c7c6abb85740cf8745439029bf0f4d35/packages/block-library/src/heading/block.json#L5-L25) 显示该区块具有 `level` 属性,并支持 `anchor` 参数。
|
||||
|
||||
如果您没有安装 Gutenberg 插件,可以在 `wp-includes/blocks/heading/block.json` 中找到 `block.json` 文件。
|
||||
|
||||
## 自定义文章类型
|
||||
|
||||
自定义文章类型可以在注册过程中注册自己的模板:
|
||||
|
||||
```php
|
||||
function myplugin_register_book_post_type() {
|
||||
$args = array(
|
||||
'public' => true,
|
||||
'label' => '书籍',
|
||||
'show_in_rest' => true,
|
||||
'template' => array(
|
||||
array( 'core/image', array(
|
||||
'align' => 'left',
|
||||
) ),
|
||||
array( 'core/heading', array(
|
||||
'placeholder' => '添加作者...',
|
||||
) ),
|
||||
array( 'core/paragraph', array(
|
||||
'placeholder' => '添加描述...',
|
||||
) ),
|
||||
),
|
||||
);
|
||||
register_post_type( 'book', $args );
|
||||
}
|
||||
add_action( 'init', 'myplugin_register_book_post_type' );
|
||||
```
|
||||
|
||||
## 锁定
|
||||
|
||||
有时可能需要在用户界面锁定模板,使得呈现的区块无法被操作。这可以通过 `template_lock` 属性实现。
|
||||
|
||||
```php
|
||||
function myplugin_register_template() {
|
||||
$post_type_object = get_post_type_object( 'post' );
|
||||
$post_type_object->template = array(
|
||||
array( 'core/paragraph', array(
|
||||
'placeholder' => '添加描述...',
|
||||
) ),
|
||||
);
|
||||
$post_type_object->template_lock = 'all';
|
||||
}
|
||||
add_action( 'init', 'myplugin_register_template' );
|
||||
```
|
||||
|
||||
_选项:_
|
||||
|
||||
- `contentOnly` — 阻止所有操作。此外,没有内容的区块类型会从列表视图中隐藏,并且无法在区块列表中获得焦点。与其他锁定类型不同,此设置不能被子级覆盖。
|
||||
- `all` — 阻止所有操作。无法插入新区块、移动现有区块或删除区块。
|
||||
- `insert` — 阻止插入或移除区块,但允许移动现有区块。
|
||||
|
||||
锁定设置可以由 InnerBlocks 继承。如果未在 InnerBlocks 区域中设置 `templateLock`,则使用父级 InnerBlocks 区域的锁定设置。如果区块是顶级区块,则使用当前文章类型的锁定配置。
|
||||
|
||||
## 单个区块锁定
|
||||
|
||||
除了模板级锁定之外,您还可以锁定单个区块;您可以在属性级别使用 `lock` 属性来实现这一点。区块级锁定的优先级高于 `templateLock` 功能。目前,您可以锁定移动和删除区块的操作。
|
||||
|
||||
```js
|
||||
attributes: {
|
||||
// 防止区块被移动或移除。
|
||||
lock: {
|
||||
remove: true,
|
||||
move: true,
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
_选项:_
|
||||
|
||||
- `remove` — 锁定区块,防止其被移除。
|
||||
- `move` — 锁定区块,防止其被移动。
|
||||
|
||||
您可以将此功能与 `templateLock` 结合使用,通过将 `remove` 或 `move` 设置为 `false` 来锁定除单个区块之外的所有区块。
|
||||
|
||||
```php
|
||||
$template = array(
|
||||
array( 'core/image', array(
|
||||
'align' => 'left',
|
||||
) ),
|
||||
array( 'core/heading', array(
|
||||
'placeholder' => '添加作者...',
|
||||
) ),
|
||||
// 允许移动或移除段落区块。
|
||||
array( 'core/paragraph', array(
|
||||
'placeholder' => '添加描述...',
|
||||
'lock' => array(
|
||||
'move' => false,
|
||||
'remove' => false,
|
||||
),
|
||||
) ),
|
||||
);
|
||||
```
|
||||
|
||||
## 嵌套模板
|
||||
|
||||
像列区块这样的容器区块也支持模板。这是通过为区块分配嵌套模板来实现的。
|
||||
|
||||
```php
|
||||
$template = array(
|
||||
array( 'core/paragraph', array(
|
||||
'placeholder' => '添加根级段落',
|
||||
) ),
|
||||
array( 'core/columns', array(), array(
|
||||
array( 'core/column', array(), array(
|
||||
array( 'core/image', array() ),
|
||||
) ),
|
||||
array( 'core/column', array(), array(
|
||||
array( 'core/paragraph', array(
|
||||
'placeholder' => '添加内部段落'
|
||||
) ),
|
||||
) ),
|
||||
) )
|
||||
);
|
||||
```
|
||||
355
reference-guides/block-api/block-transforms.md
Normal file
355
reference-guides/block-api/block-transforms.md
Normal file
@@ -0,0 +1,355 @@
|
||||
## `ungroup` 区块解组功能
|
||||
|
||||
通过区块配置中可选的 `transforms` 键,区块可使用 `ungroup` 子键定义用于替换当前处理区块的新区块。这些新区块通常是现有内部区块的子集,但也可包含全新区块。
|
||||
|
||||
若某区块配置了 `ungroup` 转换功能,即具备解组资格,无需作为默认分组区块即可使用。通过此 API 解组区块的用户界面与默认分组区块所用的界面相同。需满足以下条件才会显示解组按钮:必须选中单个分组区块,且该区块需包含若干内部区块。
|
||||
|
||||
**ungroup** 是一个回调函数,接收被处理区块的属性及内部区块数据,需返回区块对象数组。
|
||||
|
||||
示例:
|
||||
|
||||
```js
|
||||
export const settings = {
|
||||
title: '我的分组区块标题',
|
||||
description: '我的分组区块描述',
|
||||
/* ... */
|
||||
transforms: {
|
||||
ungroup: ( attributes, innerBlocks ) =>
|
||||
innerBlocks.flatMap( ( innerBlock ) => innerBlock.innerBlocks ),
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
当我们成功匹配此内容时,除 `data-post-id` 外所有HTML属性都将被剥离。如果给定 `div` 内存在其他HTML排列方式,则无法匹配转换器。同理,若其中出现的是 `<h3>` 而非 `<h2>`,匹配也会失败。
|
||||
|
||||
在处理包含非短语内容(如带 `<summary>` 的 `<details>`)的HTML片段时,模式定义至关重要。若未声明自定义模式,编辑器在尝试通过任何区块转换前会跳过这些特殊结构。
|
||||
|
||||
### 短代码
|
||||
|
||||
此类转换支持单向转换(从短代码创建区块),作为 `raw` 转换流程的组成部分。
|
||||
|
||||
`shortcode` 类型转换对象包含以下参数:
|
||||
|
||||
- **type** _(字符串)_:固定值 `shortcode`
|
||||
- **tag** _(字符串|数组)_:可转换的短代码标签或别名列表
|
||||
- **transform** _(函数,可选)_:接收短代码属性(首参数)与 [WPShortcodeMatch](/packages/shortcode/README.md#next)(次参数)的回调函数,应返回区块对象或区块对象数组。定义此参数时将优先于 `attributes` 参数
|
||||
- **attributes** _(对象,可选)_:根据[区块配置对象](/docs/reference-guides/block-api/block-registration.md)定义的属性结构,指定区块属性来源。若某属性包含 `shortcode` 键,则应为接收短代码属性(首参数)与 [WPShortcodeMatch](/packages/shortcode/README.md#next)(次参数)的函数,并返回将存入区块注释的属性值
|
||||
- **isMatch** _(函数,可选)_:根据 [Shortcode API](https://codex.wordpress.org/Shortcode_API) 接收短代码属性的回调函数,应返回布尔值。返回 `false` 将阻止该短代码转换为此区块
|
||||
- **priority** _(数字,可选)_:控制转换应用优先级,数值较低者优先,工作机制类似 [WordPress 钩子](https://developer.wordpress.org/reference/#Hook_to_WordPress)。如未设置,默认优先级为 `10`
|
||||
|
||||
**示例:通过 `transform` 从短代码转换为区块**
|
||||
|
||||
使用 `transform` 方法可将现有短代码转换为其对应区块:
|
||||
|
||||
```js
|
||||
transforms: {
|
||||
from: [
|
||||
{
|
||||
type: 'shortcode',
|
||||
tag: 'video',
|
||||
transform( { named: { src } } ) {
|
||||
return createBlock( 'core/video', { src } );
|
||||
},
|
||||
// 当短代码不具备正确ID时
|
||||
// 阻止其转换为此区块
|
||||
isMatch( { named: { id } } ) {
|
||||
return id === 'my-id';
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
```
|
||||
|
||||
**示例:通过 `attributes` 从短代码转换为区块**
|
||||
|
||||
使用 `attributes` 参数可将现有短代码转换为其对应区块:
|
||||
|
||||
```js
|
||||
transforms: {
|
||||
from: [
|
||||
{
|
||||
type: 'shortcode',
|
||||
tag: 'youtube',
|
||||
attributes: {
|
||||
url: {
|
||||
type: 'string',
|
||||
source: 'attribute',
|
||||
attribute: 'src',
|
||||
selector: 'img',
|
||||
},
|
||||
align: {
|
||||
type: 'string',
|
||||
// 短代码函数将提取短代码属性
|
||||
// 转换为可存入区块注释的值
|
||||
shortcode: ( { named: { align = 'alignnone' } } ) => {
|
||||
return align.replace( 'align', '' );
|
||||
},
|
||||
},
|
||||
},
|
||||
// 当短代码不具备正确ID时
|
||||
// 阻止其转换为此区块
|
||||
isMatch( { named: { id } } ) {
|
||||
return id === 'my-id';
|
||||
},
|
||||
},
|
||||
]
|
||||
},
|
||||
```
|
||||
|
||||
# 转换功能
|
||||
|
||||
区块转换是一套API,允许区块与其他区块进行相互转换,同时也支持从其他实体转换为区块。与此API兼容的现有实体包括短代码、文件、正则表达式和原始DOM节点。
|
||||
|
||||
## 转换方向:`to` 与 `from`
|
||||
|
||||
区块通过配置项中可选的 `transforms` 键来声明支持的转换类型,其子键 `to` 和 `from` 分别存储不同方向的转换数组。例如:
|
||||
|
||||
```js
|
||||
export const settings = {
|
||||
title: '我的区块标题',
|
||||
description: '我的区块描述',
|
||||
/* ... */
|
||||
transforms: {
|
||||
from: [
|
||||
/* 支持的来源转换 */
|
||||
],
|
||||
to: [
|
||||
/* 支持的目标转换 */
|
||||
],
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
## 转换类型
|
||||
|
||||
本节将介绍区块支持的现有转换类型:
|
||||
|
||||
- block(区块)
|
||||
- enter(回车)
|
||||
- files(文件)
|
||||
- prefix(前缀)
|
||||
- raw(原始)
|
||||
- shortcode(短代码)
|
||||
|
||||
### 区块转换
|
||||
|
||||
此类转换支持双向转换,允许区块转换为其他类型的区块。在区块工具栏中有对应的UI控件。
|
||||
|
||||
`block` 类型的转换对象包含以下参数:
|
||||
|
||||
- **type**(字符串):值为 `block`
|
||||
- **blocks**(数组):已知区块类型列表。支持通配符值(`"*"`),表示该转换适用于所有区块类型(例如:所有区块都能转换为 `core/group`)
|
||||
- **transform**(函数):接收被处理区块属性及内部区块的回调函数,应返回区块对象或区块对象数组
|
||||
- **isMatch**(函数,可选):接收区块属性(第一参数)和区块对象(第二参数)的回调函数,应返回布尔值。返回 `false` 将隐藏该转换选项
|
||||
- **isMultiBlock**(布尔值,可选):是否支持多选区块转换。为true时,`transform` 函数的首个参数为属性数组,第二参数为内部区块数组。默认为false
|
||||
- **priority**(数字,可选):控制转换优先级,数值越低优先级越高。行为类似[WordPress钩子](https://developer.wordpress.org/reference/#Hook_to_WordPress),默认优先级为 `10`
|
||||
|
||||
**示例:从段落区块转换为标题区块**
|
||||
|
||||
在标题区块配置中添加以下代码(使用 [`wp-blocks` 包](/packages/blocks/README.md#createBlock) 的 `createBlock` 函数):
|
||||
|
||||
```js
|
||||
transforms: {
|
||||
from: [
|
||||
{
|
||||
type: 'block',
|
||||
blocks: [ 'core/paragraph' ],
|
||||
transform: ( { content } ) => {
|
||||
return createBlock( 'core/heading', {
|
||||
content,
|
||||
} );
|
||||
},
|
||||
},
|
||||
]
|
||||
},
|
||||
```
|
||||
|
||||
**示例:含内部区块的转换**
|
||||
|
||||
具有InnerBlocks的区块可与其他含内部区块的区块相互转换:
|
||||
|
||||
```js
|
||||
transforms: {
|
||||
to: [
|
||||
{
|
||||
type: 'block',
|
||||
blocks: [ 'some/block-with-innerblocks' ],
|
||||
transform: ( attributes, innerBlocks ) => {
|
||||
return createBlock(
|
||||
'some/other-block-with-innerblocks',
|
||||
attributes,
|
||||
innerBlocks
|
||||
);
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
```
|
||||
|
||||
### 回车转换
|
||||
|
||||
此类转换仅支持来源转换,允许根据用户输入内容创建区块。当用户输入内容后按回车键时,将在新行中触发转换。
|
||||
|
||||
`enter` 类型的转换对象包含以下参数:
|
||||
|
||||
- **type**(字符串):值为 `enter`
|
||||
- **regExp**(正则表达式):用于匹配的正则表达式,匹配成功则触发转换
|
||||
- **transform**(函数):接收包含输入内容的回调函数,应返回区块对象或区块对象数组
|
||||
- **priority**(数字,可选):控制转换优先级,数值越低优先级越高。行为类似[WordPress钩子](https://developer.wordpress.org/reference/#Hook_to_WordPress),默认优先级为 `10`
|
||||
|
||||
**示例:通过 --- 创建分隔符区块**
|
||||
|
||||
当用户输入三个连字符后按回车键时创建分隔符区块:
|
||||
|
||||
```js
|
||||
transforms = {
|
||||
from: [
|
||||
{
|
||||
type: 'enter',
|
||||
regExp: /^-{3,}$/,
|
||||
transform: () => createBlock( 'core/separator' ),
|
||||
},
|
||||
],
|
||||
};
|
||||
```
|
||||
|
||||
### 文件类型转换
|
||||
|
||||
此类转换支持 _from_ 方向,允许通过将文件拖拽至编辑器来创建区块。
|
||||
|
||||
`files` 类型的转换是一个包含以下参数的对象:
|
||||
|
||||
- **type**(字符串):取值为 `files`
|
||||
- **transform**(函数):接收正在处理的文件数组的回调函数,应返回区块对象或区块对象数组
|
||||
- **isMatch**(函数,可选):接收正在处理的文件数组的回调函数,应返回布尔值。返回 `false` 将阻止应用此转换
|
||||
- **priority**(数字,可选):控制转换应用的优先级,数值较低的优先级高于数值较高的优先级。其行为类似于 [WordPress 钩子](https://developer.wordpress.org/reference/#Hook_to_WordPress)。与钩子类似,未设置时的默认优先级为 `10`
|
||||
|
||||
**示例:从文件创建文件区块**
|
||||
|
||||
当用户将文件拖拽至编辑器时,可通过以下代码创建文件区块:
|
||||
|
||||
```js
|
||||
transforms: {
|
||||
from: [
|
||||
{
|
||||
type: 'files',
|
||||
isMatch: ( files ) => files.length === 1,
|
||||
// 通过定义低于默认值10的优先级,
|
||||
// 使其在没有找到其他转换时作为备用方案创建文件区块
|
||||
priority: 15,
|
||||
transform: ( files ) => {
|
||||
const file = files[ 0 ];
|
||||
const blobURL = createBlobURL( file );
|
||||
// 文件将在 componentDidMount() 中上传
|
||||
return createBlock( 'core/file', {
|
||||
href: blobURL,
|
||||
fileName: file.name,
|
||||
textLinkHref: blobURL,
|
||||
} );
|
||||
},
|
||||
},
|
||||
];
|
||||
}
|
||||
```
|
||||
|
||||
### 前缀类型转换
|
||||
|
||||
此类转换支持 _from_ 方向,允许根据用户输入的文本创建区块。当用户在新区块行中输入文本并添加尾随空格时触发。
|
||||
|
||||
`prefix` 类型的转换是一个包含以下参数的对象:
|
||||
|
||||
- **type**(字符串):取值为 `prefix`
|
||||
- **prefix**(字符串):匹配此转换的字符或字符序列
|
||||
- **transform**(函数):接收输入内容的回调函数,应返回区块对象或区块对象数组
|
||||
- **priority**(数字,可选):控制转换应用的优先级,数值较低的优先级高于数值较高的优先级。其行为类似于 [WordPress 钩子](https://developer.wordpress.org/reference/#Hook_to_WordPress)。与钩子类似,未设置时的默认优先级为 `10`
|
||||
|
||||
**示例:从文本创建自定义区块**
|
||||
|
||||
若要在用户输入问号时创建自定义区块,可使用以下代码:
|
||||
|
||||
```js
|
||||
transforms: {
|
||||
from: [
|
||||
{
|
||||
type: 'prefix',
|
||||
prefix: '?',
|
||||
transform( content ) {
|
||||
return createBlock( 'my-plugin/question', {
|
||||
content,
|
||||
} );
|
||||
},
|
||||
},
|
||||
];
|
||||
}
|
||||
```
|
||||
|
||||
### 原始内容类型转换
|
||||
|
||||
此类转换支持 _from_ 方向,允许根据原始 HTML 节点创建区块。当用户执行区块设置界面菜单中的"转换为区块"操作,或向编辑器粘贴/拖拽内容时触发。
|
||||
|
||||
`raw` 类型的转换是一个包含以下参数的对象:
|
||||
|
||||
- **type**(字符串):取值为 `raw`
|
||||
- **transform**(函数,可选):接收正在处理节点的回调函数,应返回区块对象或区块对象数组
|
||||
- **schema**(对象|函数,可选):定义用于检测和处理粘贴内容的 [HTML 内容模型](https://html.spec.whatwg.org/multipage/dom.html#content-models),详见[下文](#内容模型与架构)
|
||||
- **selector**(字符串,可选):用于根据 [element.matches](https://developer.mozilla.org/en-US/docs/Web/API/Element/matches) 方法判断元素是否匹配的 CSS 选择器字符串。若元素不匹配则不会执行转换。这是 `isMatch` 的简写替代方案,若同时存在则优先使用 `isMatch`
|
||||
- **isMatch**(函数,可选):接收正在处理节点的回调函数,应返回布尔值。返回 `false` 将阻止应用此转换
|
||||
- **priority**(数字,可选):控制转换应用的优先级,数值较低的优先级高于数值较高的优先级。其行为类似于 [WordPress 钩子](https://developer.wordpress.org/reference/#Hook_to_WordPress)。与钩子类似,未设置时的默认优先级为 `10`
|
||||
|
||||
**示例:从 URL 创建嵌入区块**
|
||||
|
||||
若要在用户向编辑器粘贴 URL 时创建嵌入区块,可使用以下代码:
|
||||
|
||||
```js
|
||||
transforms: {
|
||||
from: [
|
||||
{
|
||||
type: 'raw',
|
||||
isMatch: ( node ) =>
|
||||
node.nodeName === 'P' &&
|
||||
/^\s*(https?:\/\/\S+)\s*$/i.test( node.textContent ),
|
||||
transform: ( node ) => {
|
||||
return createBlock( 'core/embed', {
|
||||
url: node.textContent.trim(),
|
||||
} );
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
```
|
||||
|
||||
<h4 id="内容模型与架构">内容模型与架构</h4>
|
||||
|
||||
在粘贴内容时,可以定义用于验证和处理粘贴内容的[内容模型](https://html.spec.whatwg.org/multipage/dom.html#content-models)。粘贴到编辑器中的 HTML 通常包含应当转移和不应转移的混合元素。例如考虑将 `<span class="time">12:04 pm</span>` 粘贴到编辑器中的情况:我们需要复制 `12:04 pm` 并忽略 `<span>` 及其 `class` 属性,因为这些元素在复制后不再具有原有的含义和结构。
|
||||
|
||||
在编写 `raw` 转换时,可通过提供描述允许内容的 `schema` 来控制此行为,该架构将在尝试与区块匹配之前对粘贴内容进行清理。这些架构会传入 [`@wordpress/dom` 中的 `cleanNodeList`](https://github.com/wordpress/gutenberg/blob/trunk/packages/dom/src/dom/clean-node-list.js);请查阅该处获取[架构的完整描述](https://github.com/wordpress/gutenberg/blob/trunk/packages/dom/src/phrasing-content.js)。
|
||||
|
||||
```js
|
||||
schema = { span: { children: { '#text': {} } } };
|
||||
```
|
||||
|
||||
**示例:自定义内容模型**
|
||||
|
||||
假设我们需要匹配以下 HTML 片段并将其转换为某种自定义文章预览区块:
|
||||
|
||||
```html
|
||||
<div data-post-id="13">
|
||||
<h2>文章标题</h2>
|
||||
<p>一段<em>精彩</em>内容</p>
|
||||
</div>
|
||||
```
|
||||
|
||||
我们需要通过提供以下架构来告知编辑器允许内部的 `h2` 和 `p` 元素。此示例中使用函数形式,该函数接收包含 `phrasingContentSchema` 的参数(以及指示转换操作是否以粘贴文本开始的布尔值 `isPaste`)。`phrasingContentSchema` 预定义为匹配 HTML 短语元素,如 `<strong>`、`<sup>` 和 `<kbd>`。任何期望使用 `<RichText />` 组件的地方都适合允许短语内容,否则在转换过程中将丢失所有文本格式。
|
||||
|
||||
```js
|
||||
schema = ({ phrasingContentSchema }) => {
|
||||
div: {
|
||||
required: true,
|
||||
attributes: [ 'data-post-id' ],
|
||||
children: {
|
||||
h2: { children: phrasingContentSchema },
|
||||
p: { children: phrasingContentSchema }
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
248
reference-guides/block-api/block-variations.md
Normal file
248
reference-guides/block-api/block-variations.md
Normal file
@@ -0,0 +1,248 @@
|
||||
# 区块变体
|
||||
|
||||
区块变体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`。
|
||||
Reference in New Issue
Block a user