gutenbergdocs/reference-guides/block-api/block-attributes.md
2025-10-22 01:33:45 +08:00

495 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 属性
区块属性提供了关于区块存储数据的信息。例如富文本内容、图片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": "小图" }
]
}
```