块属性提供了关于块存储的数据的信息。例如,富内容、图像 URL 列表、背景颜色或按钮标题。

一个块可以包含任意数量的属性,这些属性由 attributes 字段指定——这是一个对象,其中每个键是属性的名称,值是该属性的定义。

属性定义至少将包含 type 或 enum 之一。可能有其他字段。

示例:定义三个属性的属性对象——url、title 和 size。

{
    url: {
        type: 'string',
        source: 'attribute',
        selector: 'img',
        attribute: 'src',
    },
    title: {
        type: 'string',
    },
    size: {
        enum: [ 'large', 'small' ],
    },
}

当块被解析时,此定义将用于从块内容中提取数据。任何匹配的内容都可以通过 attributes prop 提供给您的块。

此解析过程可以总结为:

  1. 从 source 中提取值。
  2. 检查值是否匹配 type,或者是 enum 值之一。

示例:在 edit 和函数中可用的属性,使用上述属性定义。

function YourBlockEdit( { attributes } ) {
    return (
        <p>URL is { attributes.url }, title is { attributes.title }, and size is { attributes.size }.</p>
    )
}

块负责使用 save 函数确保所有具有 source 字段的属性都根据属性定义进行保存。这不是自动的。

没有 source 的属性将自动保存在块的 注释分隔符 中。

例如,使用上述属性定义,您需要确保您的 save 函数为 url 属性具有相应的 img 标签。title 和 size 属性将保存在注释分隔符中。

示例:包含 url 属性的示例 save 函数。

function YourBlockSave( { attributes } ) {
    return (
        <img src={ attributes.url } />
    )
}

保存的 HTML 将包含注释分隔符中的 title 和 size,以及 img 节点中的 url。

<!-- block:your-block {"title":"hello world","size":"large"} -->
<img src="/image.jpg" />
<!-- /block:your-block -->

如果属性随时间变化,则 块弃用 可以帮助从旧属性迁移或完全删除它。

类型验证

type 指示属性存储的数据类型。它不指示数据存储的位置,这由 source 字段定义。

除非提供 enum,否则需要 type。type 可以与 enum 一起使用。

type 字段必须是以下之一:

  • null
  • boolean
  • object
  • array
  • string
  • integer
  • number(与 integer 相同)

请注意,object 的有效性由您的 source 确定。示例请参见下面的 query 详情。

枚举验证

属性可以定义为固定值集之一。这由 enum 指定,其中包含允许值的数组:

示例:示例 enum。

{
    size: {
        enum: [ 'large', 'small', 'tiny' ]
    }
}

值源

属性源用于定义如何从保存的帖子内容中提取属性值。它们提供了一种机制,将保存的标记映射到块的 JavaScript 表示。

可用的 source 值为:
– (无值) – 当未指定 source 时,数据存储在块的 注释分隔符 中。
– attribute – 数据存储在 HTML 元素属性中。
– text – 数据存储在 HTML 文本中。
– html – 数据存储在 HTML 中。这通常由 RichText 使用。
– query – 数据作为对象数组存储。
– meta – 数据存储在帖子元数据中(已弃用)。

source 字段通常与 selector 字段结合使用。如果未指定选择器参数,则源定义针对块的根节点运行。如果指定了选择器参数,它将针对块内的匹配元素运行。

selector 可以是 HTML 标签,或任何可通过 querySelector 查询的内容,例如类或 id 属性。下面给出了示例。

例如,img 的 selector 将匹配 img 元素,而 img.class 将匹配具有 class 类的 img 元素。

在底层,属性源是 hpq 提供的功能的超集,这是一个用于解析和查询 HTML 标记为对象形状的小型库。

总之,source 确定数据存储在您的内容中的位置,而 type 确定该数据是什么。为了减少存储的数据量,通常最好在 HTML 中存储尽可能多的数据,而不是在注释分隔符中的属性中存储。

attribute 源

使用 attribute 源从标记中的属性提取值。属性由 attribute 字段指定,必须提供该字段。

示例:从块标记中找到的图像中提取 src 属性。

保存的内容:

<div>
    Block Content

    <img src="https://lorempixel.com/1200/800/" />
</div>

属性定义:

{
    url: {
        type: 'string',
        source: 'attribute',
        selector: 'img',
        attribute: 'src',
    }
}

块中可用的属性:

{ "url": "https://lorempixel.com/1200/800/" }

来自标记的大多数属性类型均为 string。HTML 中的数字属性仍然存储为字符串,并且不会自动转换。

示例:从块标记中找到的图像中提取 width 属性。

保存的内容:

<div>
    Block Content

    <img src="https://lorempixel.com/1200/800/" width="50" />
</div>

属性定义:

{
    width: {
        type: 'string',
        source: 'attribute',
        selector: 'img',
        attribute: 'width',
    }
}

块中可用的属性:

{ "width": "50" }

唯一的例外是检查属性的存在性(例如,button 上的 disabled 属性)。在这种情况下,可以使用类型 boolean,存储的值将是布尔值。

示例:从块标记中找到的按钮中提取 disabled 属性。

保存的内容:

<div>
    Block Content

    <button type="button" disabled>Button</button>
</div>

属性定义:

{
    disabled: {
        type: 'boolean',
        source: 'attribute',
        selector: 'button',
        attribute: 'disabled',
    }
}

块中可用的属性:

{ "disabled": true }

text 源

使用 text 从标记中提取内部文本。请注意,HTML 是根据 textContent 的规则返回的。

示例:从块标记中找到的 figcaption 元素中提取 content 属性。

保存的内容:

<figure>
    <img src="/image.jpg" />

    <figcaption>The inner text of the figcaption element</figcaption>
</figure>

属性定义:

{
    content: {
        type: 'string',
        source: 'text',
        selector: 'figcaption',
    }
}

块中可用的属性:

{ "content": "The inner text of the figcaption element" }

另一个示例,使用 text 作为源,并使用 .my-content 类作为选择器来提取文本:

示例:从块标记中发现的具有 .my-content 类的元素中提取 content 属性。

保存的内容:

<div>
    <img src="/image.jpg" />

    <p class="my-content">The inner text of .my-content class</p>
</div>

属性定义:

{
    content: {
        type: 'string',
        source: 'text',
        selector: '.my-content',
    }
}

块中可用的属性:

{ "content": "The inner text of .my-content class" }

html 源

使用 html 从标记中提取内部 HTML。请注意,文本的返回遵循 innerHTML 的规则。

示例:从块标记中发现的 figcaption 元素中提取 content 属性。

保存的内容:

<figure>
    <img src="/image.jpg" />

    <figcaption>The inner text of the <strong>figcaption</strong> element</figcaption>
</figure>

属性定义:

{
    content: {
        type: 'string',
        source: 'html',
        selector: 'figcaption',
    }
}

块中可用的属性:

{ "content": "The inner text of the <strong>figcaption</strong> element" }

query 源

使用 query 从标记中提取值数组。数组的条目由 selector 参数确定,其中块内的每个匹配元素都将有一个条目,其结构对应于第二个参数,即属性源对象。

query 字段实际上是一个嵌套的块属性定义。可以(尽管不一定推荐)进一步嵌套。

示例:从块标记中的每个图像元素中提取 src 和 alt。

保存的内容:

<div>
    <img src="https://lorempixel.com/1200/800/" alt="large image" />
    <img src="https://lorempixel.com/50/50/" alt="small image" />
</div>

属性定义:

{
    images: {
        type: 'array',
        source: 'query',
        selector: 'img',
        query: {
            url: {
                type: 'string',
                source: 'attribute',
                attribute: 'src',
            },
            alt: {
                type: 'string',
                source: 'attribute',
                attribute: 'alt',
            },
        }
    }
}

块中可用的属性:

{
    "images": [
        { "url": "https://lorempixel.com/1200/800/", "alt": "large image" },
        { "url": "https://lorempixel.com/50/50/", "alt": "small image" }
    ]
}

Meta 源 (deprecated)

虽然属性可以从帖子的元数据中获取,但元数据属性源被视为已弃用;应使用 EntityProvider 和相关钩子 API,如 创建元数据块教程 所示。

属性可以从帖子的元数据中获取,而不是从保存的帖子内容中的块的表示形式中获取。为此,需要一个属性来指定其在 meta 键下的相应元数据键。

属性定义:

{
    author: {
        type: 'string',
        source: 'meta',
        meta: 'author'
    },
},

从此时起,块可以使用与任何属性相同的接口来读取和写入元数据属性:

edit( { attributes, setAttributes } ) {
    function onChange( event ) {
        setAttributes( { author: event.target.value } );
    }

    return <input value={ attributes.author } onChange={ onChange } type="text" />;
},

注意事项

默认情况下,元数据字段将从帖子对象的元数据中排除。可以通过显式使字段可见来绕过这一点:

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 参数,如下所示:

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 字符串。请记住,您有责任确保数据的完整性;请确保正确清理、处理缺失数据等。

最后,在设置属性时,请确保尊重数据的类型,因为框架不会自动对元数据进行类型转换。块属性中的错误类型将导致帖子在保存后仍然保持脏状态(cf. isEditedPostDirty, hasEditedAttributes)。例如,如果 authorCount 是整数,请记住事件处理程序可能会传递不同类型的数据,因此应显式转换该值:

function onChange( event ) {
    props.setAttributes( { authorCount: Number( event.target.value ) } );
}

默认值

块属性可以包含默认值,如果 type 和 source 与块内容中的任何内容不匹配,则使用该默认值。

该值由 default 字段提供,并且该值应符合属性的预期格式。

示例:default 值的示例。

{
    type: 'string',
    default: 'hello world'
}
{
    type: 'array',
    default: [
        { "url": "https://lorempixel.com/1200/800/", "alt": "large image" },
        { "url": "https://lorempixel.com/50/50/", "alt": "small image" }
    ]
}
{
    type: 'object',
    default: {
        width: 100,
        title: 'title'
    }
}

角色

role 属性将属性指定为特定概念类型。此属性可以应用于任何属性,以提供有关应如何处理属性的语义含义。

使用 content 将属性指定为用户可编辑的内容。标记为 content 的块可以在特殊情况下(例如仅内容锁定)启用特权编辑。
使用 local 将属性标记为临时且不可持久化。标记为 local 的属性会被块序列化器忽略,并且永远不会保存到帖子内容中。

示例:段落块使用的 content 角色。

{
    content: {
        type: 'string',
        source: 'html',
        selector: 'p',
        role: 'content',
    }
}

示例:用于临时数据的 local 角色。

{
    blob: {
        type: 'string',
        role: 'local',
    }
}

在 WordPress 6.7 开发说明 中了解更多。