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

13 KiB
Raw Blame History

属性

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

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

属性定义至少包含typeenum之一,也可能包含其他字段。

示例:定义三个属性(urltitlesize)的属性对象。

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

当区块被解析时,此定义将用于从区块内容中提取数据。所有匹配项都会通过attributes属性提供给您的区块。

该解析过程可概括为:

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

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

function YourBlockEdit( { attributes } ) {
	return (
		<p>URL是{ attributes.url }标题是{ attributes.title }尺寸是{ attributes.size }</p>
	)
}

区块需负责使用save函数确保所有带source字段的属性按照属性定义保存。此过程非自动执行。

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

例如,使用上述属性定义时,您需要确保save函数包含与url属性对应的img标签。titlesize属性将保存在注释分隔符中。

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

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

保存的HTML将在注释分隔符中包含titlesize,在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选择器将匹配img元素,而img.class将匹配具有class类的img元素。

在底层实现中,属性来源是hpq库功能的超集该小型库用于将HTML标记解析和查询为对象形态。

总结而言,source决定数据在内容中的存储位置,而type决定数据的类型。为减少存储数据量通常建议尽可能将数据存储在HTML中而非注释分隔符内的属性中。

元数据源(已弃用)

虽然属性可从文章的元数据中获取,但元数据属性源已被视为弃用;应改用 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 字符串。请注意,您需要负责数据的完整性;确保正确清理数据、处理缺失数据等。

最后,请确保在设置属性时尊重数据的类型,因为框架不会自动执行元数据的类型转换。块属性中的类型错误将导致文章即使在保存后仍保持“脏”状态(参见 isEditedPostDirtyhasEditedAttributes)。例如,如果 authorCount 是整数类型,请记住事件处理程序可能会传递不同类型的数据,因此应显式转换值:

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

默认值

块属性可以包含默认值,当 typesource 与块内容中的任何内容不匹配时,将使用该值。

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

示例default 值的示例。

{
	type: 'string',
	default: 'hello world'
}
{
	type: 'array',
	default: [
		{ "url": "https://lorempixel.com/1200/800/", "alt": "大图" },
    	{ "url": "https://lorempixel.com/50/50/", "alt": "小图" }
	]
}
{
	type: 'object',
	default: {
		width: 100,
		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 开发说明

attribute 数据源

使用 attribute 数据源可从标记中提取属性值。通过必须提供的 attribute 字段指定需要提取的属性。

示例:从区块标记中的图片元素提取 src 属性。

保存内容:

<div>
	区块内容

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

属性定义:

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

区块中可用的属性:

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

大多数标记中的属性都是字符串类型。HTML中的数值属性仍会以字符串形式存储且不会自动转换。

示例:从区块标记中的图片元素提取 width 属性。

保存内容:

<div>
	区块内容

	<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>
	区块内容

	<button type="button" disabled>按钮</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>figcaption 元素的内部文本</figcaption>
</figure>

属性定义:

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

区块中可用的属性:

{ "content": "figcaption 元素的内部文本" }

另一个使用 text 数据源,通过 .my-content 类选择器提取文本的示例:

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

保存内容:

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

	<p class="my-content">.my-content 类的内部文本</p>
</div>

属性定义:

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

区块中可用的属性:

{ "content": ".my-content 类的内部文本" }

html 数据源

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

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

保存内容:

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

	<figcaption><strong>figcaption</strong> 元素的内部文本</figcaption>
</figure>

属性定义:

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

区块中可用的属性:

{ "content": "<strong>figcaption</strong> 元素的内部文本" }

query 数据源

使用 query 可从标记中提取值数组。数组条目由 selector 参数决定,区块内每个匹配元素都会对应一个条目,其结构由第二个参数(属性源对象)定义。

query 字段实际上是嵌套的区块属性定义。虽然可以进一步嵌套(但不一定推荐这样做)。

示例:从区块标记中的每个图片元素提取 srcalt 属性。

保存内容:

<div>
	<img src="https://lorempixel.com/1200/800/" alt="大图" />
	<img src="https://lorempixel.com/50/50/" alt="小图" />
</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": "大图" },
		{ "url": "https://lorempixel.com/50/50/", "alt": "小图" }
	]
}