属性

Topics

  • タイプの検証
  • enum の検証
  • 値のソース
    • attribute ソース
    • text ソース
    • html ソース
    • query ソース
    • meta ソース (非推奨)
      • 考慮点
    • デフォルト値

「ブロック属性」は、ブロックによって保存されるデータについての情報を提供します。例えば、リッチコンテンツ、画像 URL のリスト、背景色、ボタンのタイトルなどです。

ブロックは任意の数の属性を含むことができ、属性は attributes フィールドで指定されます。この attributes フィールドは、属性名をキー、属性定義を値にもつオブジェクトです。

属性定義には、最低でも type または enum のいずれかが含まれ、オプションで追加のフィールドを含みます。

: 3つの属性 urltitlesize を定義する属性オブジェクト

{
	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 は属性に格納されているデータの種類を示します。type はデータがどこに保存されているかは示しません。これは source フィールドによって定義されます。

enum が提供されない限り、type は必須です。type は enum と一緒に使用できます。

type フィールドは以下でなければなりません。

  • null
  • boolean
  • object
  • array
  • string
  • integer
  • number (integer と同じ)

object の検証は、source によって決定されることに注意してください。例として、以下の「query」の詳細を参照してください。

Top ↑

enum の検証

属性は固定された値のセットの一つとして定義できます。これには enum を指定し、許可される値の配列を含めます。

enum の例

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

Top ↑

値のソース

「属性ソース」は、保存された投稿コンテンツから、どのように属性値を取り出すかを定義します。属性ソースは、保存されたマークアップから、ブロックのJavaScript表現にマッピングするメカニズムを提供します。

可能な source の値は以下のとおりです。

値:

  • (値なし) – source が指定されていない場合、データはブロックのコメントデリミタに保存されます。
  • attribute – データは、HTML 要素の属性に保存されます。
  • text – データは、HTML テキストに保存されます。
  • html – データは、HTML に保存されます。この典型的な使用例は RichText です。
  • query – データは、オブジェクトの配列に保存されます。
  • meta – データは、投稿メタに保存されます (非推奨)。

sourceフィールドは通常、selector フィールドと組み合わせて使用します。selector が指定されていない場合、ソース定義はブロックのルートノードに対して実行されます。selector がある場合は、ブロック内の合致する要素に対して実行されます。

selectorには、HTMLタグのほか、querySelector で問い合わせ可能なもの、たとえば class や id 属性などを指定できます。以下に例を示します。

例えば、img の selector は img 要素に合致し、img.class は、クラス class を持つ img 要素に合致します。

実装から見た場合、属性ソースは hpq によって提供される機能の上位セットとなる小さなライブラリーです。HTML マークアップを解析してオブジェクト形式にクエリーします。

まとめると、source はコンテンツのどこにデータが保存されるかを決定し、type はそのデータが何であるかを決定します。保存されるデータの量を減らすには、通常、できるだけ多くのデータを、コメントデリミタ内の属性としてではなく、HTML 内に保存した方がよいでしょう。

Top ↑

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 を使用でき、保存した値も boolean になります。

: ブロックのマークアップにあるボタンから、disabled 属性を取り出す。

保存されたコンテンツ:

<div>
	Block Content

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

属性定義:

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

ブロック内で利用可能な属性:

{ "disabled": true }

Top ↑

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" }

次の例では source として text、selector として .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" }

Top ↑

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" }

Top ↑

query ソース

マークアップから値の配列を取り出すには query を使用します。配列のエントリーは selector 引数によって決定されます。このとき、ブロック内で合致した各要素は、2番目の引数である属性ソースのオブジェクトに対応するエントリー構造を持ちます。

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" }
	]
}

Top ↑

meta ソース (非推奨)

注意
投稿の meta から属性を取得できますが、meta 属性ソースは非推奨です。代わりに 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" />;
},

Top ↑

考慮点

デフォルトではメタフィールドは投稿オブジェクトのメタから除外されます。これを回避するにはフィールドを明示的に見えるようにします。

function gutenberg_my_block_init() {
	register_post_meta( 'post', 'author', array(
		'show_in_rest' => true,
	) );
}
add_action( 'init', 'gutenberg_my_block_init' );

さらに WordPress のデフォルトに注意してください。

  • 1つのメタデータを単一として扱わず、代わりに値の配列を返します。
  • データを文字列として扱います。

どちらの動きも希望しない場合には、同じ 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 文字列をデシリアライズします。このときデータの整合性に責任があることに注意してください。適切なサニタイズや失われたデータの調節などが必要です。

最後に属性を設定する差にはデータのタイプを尊重してください。なぜならフレームワークは自動でメタの型変換を実行しないためです。ブロック属性の誤った型は保存した後も投稿を dirty のままにします (参照 isEditedPostDirtyhasEditedAttributes)。たとえば authorCount が integer なら、イベントハンドラは異なる種類のdataを渡す可能性があるため、値を明示的に型変換する必要があります。

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

Top ↑

デフォルト値

ブロック属性にはデフォルト値を持てます。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'
	}
}

原文

最終更新日: