Gutenberg の動的ブロックを作成する方法
公開: 2022-08-03あなたはまだグーテンベルクに戸惑っていますか? それとも、ブロック エディターの可能性を固く信じており、ブロック エディターを使用して自分の創造性をどこまで押し上げることができるかを知りたいですか?
あなたがどのカテゴリーのユーザーに属していても、グーテンベルクはここにとどまります. しかし、それだけではありません!
Gutenberg ブロック開発の一般的な紹介を提供した以前のチュートリアルに続いて、この記事では基本を超えて、より高度なブロック タイプを紹介します。 これらのブロックは、動的ブロックと呼ばれます。
今日は、動的ブロックとは何か、それらがどのように機能するか、および動的ブロックをゼロから作成するために知っておく必要があるすべてのことを学びます。
では、グーテンベルグの動的ブロックとは何ですか?また、静的ブロックと動的ブロックの主な違いは何ですか?
ダイナミック ブロックとは例
静的ブロックでは、投稿またはページの編集中にコンテンツがユーザーによって手動で追加されますが、動的ブロックでは、コンテンツはページの読み込み時にオンザフライで読み込まれ、処理されます。 動的ブロックを使用すると、ブロックのコンテンツがデータベースから取得され、そのまま表示されるか、あらゆる種類のデータ操作の結果として表示されます。
例を挙げて説明しましょう。 ネストされたブロックのグループを作成して、投稿者の詳細を表示し、同じ著者からの最新の投稿を選択するとします。
Gutenberg ユーザーとして、次のブロックを使用できます。
- 見出しコアブロック
- Post Authorコアブロック
- 最新の投稿コア ブロック
これらのブロックを含むグループを作成し、将来の使用のためにそのグループを再利用可能なブロックに追加することもできます。
とても簡単ですね。 動的ブロックを作成して、投稿やページに簡単に追加できます。
WordPress 5.9 の時点で、ブロック エディターには 90 を超えるさまざまなブロックが用意されています。 さらに必要な場合は、WordPress プラグイン ディレクトリでクイック検索を実行すると、追加のブロックを提供する無料のプラグインがたくさん見つかります。
しかし、あなたが WordPress 開発者である場合、または WordPress 開発者としてのキャリアを計画している場合はどうでしょうか? おそらく、非常に具体的なニーズがあり、探しているブロックが見つからないか、単に新しい専門的なスキルを習得したいだけです。 このような状況では、ダイナミック ブロックの作成方法を学習することをお勧めします。
開発者の視点から見た Gutenberg ダイナミック ブロック
ダイナミック ブロックには、主に 2 つのユース ケースがあります。
最初の使用例は、ブロックを含むページが更新されていないときにブロックのコンテンツを更新する必要がある場合です。 たとえば、ブロックに最新の投稿やコメントのリストが含まれている場合や、一般に、データベースから取得したデータを使用してブロックのコンテンツが動的に生成される場合に発生します。
2 番目のユース ケースは、ブロック コードの更新をフロント エンドにすぐに表示する必要がある場合です。 静的ブロックの代わりに動的ブロックを使用すると、ブロックのすべてのオカレンスに変更がすぐに適用されます。
一方、静的ブロックによって生成された HTML を変更すると、ブロックの以前のバージョンのすべてのインスタンスが削除されて新しいバージョンに置き換えられるか、古いバージョンをマークするまで、無効化ダイアログがユーザーに表示されます。バージョンは廃止予定です (廃止予定とブロックの検証、廃止予定と移行の経験も参照してください)。
そうは言っても、動的ブロックの構築を開始する前に理解する必要がある概念がいくつかあります。
アプリケーションの状態とデータ ストア
Gutenberg は React SPA アプリケーションであり、Gutenberg のすべてが React コンポーネントです。 投稿のタイトル、ヘッダー、段落、画像、およびエディター内の HTML コンテンツのブロックはすべて React コンポーネントであり、サイドバーとブロック ツールバー コントロールも同様です。
前回の記事では、プロパティのみを使用してデータを保存しました。 この記事では、 stateの概念を導入して、さらに一歩進めます。
簡単に言うと、 state
オブジェクトは、コンポーネントに関する情報を格納するために使用されるプレーンな JavaScript オブジェクトです。 コンポーネントのstate
は時間の経過とともに変化する可能性があり、状態が変化するたびに、コンポーネントは再レンダリングされます。
state
オブジェクトと同様に、プロパティはコンポーネントに関する情報を保持するために使用されるプレーンな JavaScript オブジェクトです。 しかし、props とstate
には重要な違いがあります。
props
はコンポーネントに渡されますが (関数パラメーターと同様)、state
はコンポーネント内で管理されます (関数内で宣言された変数と同様)。
状態は、アプリケーションがコンポーネントの動作を制御するために保存する、特定の時点で取得されたデータのスナップショットと考えることができます。 たとえば、ブロック エディターの設定サイドバーが開いている場合、情報の一部がstate
オブジェクトのどこかに保存されます。
情報が単一のコンポーネント内で共有される場合、それをローカル状態と呼びます。 アプリケーション内のコンポーネント間で情報が共有される場合、それをApplication Stateと呼びます。
アプリケーションの状態は、ストアの概念と密接に関連しています。 Reduxのドキュメントによると:
ストアは、アプリケーションの状態ツリー全体を保持します。 内部の状態を変更する唯一の方法は、アクションをディスパッチすることです。
そのため、Redux はアプリケーションの状態を単一の不変オブジェクト ツリー (ストア) に格納します。 オブジェクト ツリーは、アクションとリデューサーを使用して新しいオブジェクトを作成することによってのみ変更できます。
WordPress では、ストアはWordPress データ モジュールによって管理されます。
Gutenberg のモジュール性、パッケージ、およびデータ ストア
Gutenberg リポジトリは、いくつかの再利用可能で独立したモジュールでゼロから構築されており、それらを組み合わせて編集インターフェイスを構築します。 これらのモジュールは、パッケージとも呼ばれます。
公式ドキュメントには、2 つの異なるタイプのパッケージがリストされています。
- 製品パッケージは、ブラウザーで実行される製品コードを構成します。 WordPress には 2 種類の運用パッケージがあります。
- スタイルシートを含むパッケージは、適切に機能するスタイルシートを提供します。
- データ ストアを含むパッケージは、その状態を処理するデータ ストアを定義します。 データストアを含むパッケージは、サードパーティのプラグインとテーマで使用して、データを取得および操作できます。
- 開発パッケージは開発モードで使用されます。 これらのパッケージには、リンティング、テスト、ビルドなどのツールが含まれています。
ここでは主に、データの取得と操作に使用されるデータ ストアを含むパッケージに関心があります。
WordPress データストア
WordPress データ モジュールは Redux に基づいて構築されており、3 つの Redux コア原則を共有していますが、いくつかの重要な違いがあります。
公式ドキュメントでは、次の定義が提供されています。
WordPress のデータ モジュールは、プラグインと WordPress 自体の両方のアプリケーション状態を管理するためのハブとして機能し、個別のモジュール内およびモジュール間でデータを管理するためのツールを提供します。 これは、データを整理して共有するためのモジュラー パターンとして設計されています。小さなプラグインのニーズを満たすのに十分シンプルでありながら、複雑な単一ページ アプリケーションの要件に対応できるスケーラブルです。
デフォルトでは、Gutenberg はアプリケーション状態内に複数のデータ ストアを登録します。 これらの各ストアには、特定の名前と目的があります。
-
core
: WordPress コアデータ core/annotations
: 注釈core/blocks
: ブロック タイプ データcore/block-editor
: ブロック エディターのデータcore/editor
: 投稿編集者のデータcore/edit-post
: エディターの UI データcore/notices
: お知らせデータcore/nux
: NUX (新しいユーザー エクスペリエンス) データcore/viewport
: ビューポート データ
これらのストアを通じて、大量のデータにアクセスできます。
- 投稿のタイトル、抜粋、カテゴリとタグ、ブロックなど、現在の投稿に関連するデータ。
- ユーザー インターフェースに関連するデータ(つまり、トグルがオンまたはオフになっている場合)。
- 登録された分類法、投稿の種類、ブログのタイトル、作成者など、WordPress のインストール全体に関連するデータ。
これらのストアは、グローバルwp
オブジェクトに存在します。 ストアの状態にアクセスするには、 select
関数を使用します。
どのように機能するかを確認するには、新しい投稿またはページを作成し、ブラウザーのインスペクターを起動します。 コンソールを見つけて、次のコード行を入力します。
wp.data.select("core")
結果は、 core
データ ストアからデータを取得するために使用できる関数のリストを含むオブジェクトになります。 これらの関数はセレクターと呼ばれ、状態値にアクセスするためのインターフェイスとして機能します。
WordPress データ ストアには、WordPress に関する一般的な情報が含まれており、セレクターはその情報を取得する方法です。 たとえば、 getCurrentUser()
は現在のユーザーの詳細を返します。
wp.data.select("core").getCurrentUser()
データ ストアからユーザーの詳細を取得するために使用できる別のセレクターは、 getUsers()
です。 :
wp.data.select("core").getUsers()
次の図は、応答オブジェクトを示しています。
1 人のユーザーの詳細を取得するには、次の行を入力するだけです。
wp.data.select("core").getUsers()[0]
同じセレクターを使用して、作成author
ロールが割り当てられたサイト ユーザーを取得することもできます。
wp.data.select( 'core' ).getUsers({ who: 'authors' })
登録されたタクソノミーを取得することもできます。
wp.data.select("core").getTaxonomies()
登録された投稿タイプのリスト:
wp.data.select("core").getPostTypes()
またはプラグインのリスト:
wp.data.select("core").getPlugins()
次に、別のデータ ストアにアクセスしてみましょう。 これを行うには、引き続きselect
関数を使用しますが、別の名前空間を提供します。 次のことを試してみましょう。
wp.data.select("core/edit-post")
これで、次の応答オブジェクトを取得できます。
設定サイドバーが開いているかどうかを知りたい場合は、 isEditorSidebarOpened
セレクターを使用します。
wp.data.select("core/edit-post").isEditorSidebarOpened()
サイドバーが開いている場合、この関数はtrue
を返します。
投稿データへのアクセス方法
これで、データへのアクセス方法の基本を理解できたはずです。 ここで、特定のセレクタであるgetEntityRecords
関数を詳しく見ていきます。これは、投稿データへのアクセスを提供するセレクタです。
ブロック エディターで、右クリックして [検査] を選択します。 [コンソール] タブで、次の行をコピーして貼り付けます。
wp.data.select("core").getEntityRecords('postType', 'post')
これにより、Rest API にリクエストが送信され、最後に公開されたブログ投稿に対応するレコードの配列が返されます。
getEntityRecords
は、次の 3 つのパラメーターを受け入れます。
-
kind
string : エンティティの種類 (つまりpostType
)。 -
name
string : エンティティ名 (つまりpost
)。 -
query
?Object : オプションの用語クエリ (つまり{author: 0}
)。
引数のオブジェクトを使用して、より具体的なリクエストを作成できます。
たとえば、特定のカテゴリの投稿のみを応答に含めるように決定できます。
wp.data.select("core").getEntityRecords('postType', 'post', {categories: 3})
特定の著者の記事のみをリクエストすることもできます。
wp.data.select("core").getEntityRecords('postType', 'post', {author: 2})
getEntityRecords
によって返されたレコードのいずれかをクリックすると、選択したレコードのプロパティのリストが表示されます。
応答に主役の画像を含めたい場合は、前の要求に引数を追加する必要があります。
wp.data.select("core").getEntityRecords('postType', 'post', {author: 2, _embed: true})
これで、WordPress データストアにアクセスして投稿の詳細を取得する方法について理解が深まったはずです。 getEntityRecords
セレクターの詳細については、getEntityRecords を使用した Gutenberg でのデータの要求も参照してください。
ダイナミック ブロックの作成方法: サンプル プロジェクト
長い理論的前提の後、以前のブロック開発チュートリアルで紹介したツールを使用して、動的ブロックの練習と作成に進むことができます。
その記事では、次のことについて説明しました。
- WordPress 開発環境のセットアップ方法
- ブロック足場とは
- 静的 Gutenberg ブロックを構築する方法
そのため、この記事ではこれらのトピックについて詳しく説明しませんが、追加情報や復習のために以前のガイドを参照してください。
JavaScript 開発環境のセットアップ
JavaScript 開発環境をセットアップすることから始めましょう。
Node.js をインストールまたは更新する
まず、Node.js をインストールまたは更新します。 完了したら、コマンド ライン ツールを起動し、次のコマンドを実行します。
node -v
ノードのバージョンが表示されます。
開発環境を設定する
次に、WordPress の開発環境が必要です。 この例では、ローカルの WordPress ウェブサイトをすぐに立ち上げることができる無料の WordPress 開発ツールである DevKinsta を使用しました。
ただし、MAMP や XAMPP、または公式の wp-env ソリューションなど、好きな WordPress ローカル開発環境を自由に選択できます。
DevKinsta を使用している場合は、[ New WordPress Site ] または [ Custom Site ] をクリックし、フォーム フィールドに入力して [ Create site ] を押します。
インストール プロセスには 1 ~ 2 分かかります。 完了したら、ローカルの WordPress 開発 Web サイトを起動します。
ブロック プラグインを設定する
今必要なのは、スターター ブロック プラグインです。 面倒な手動設定をすべて回避するために、WordPress コア開発者チームは @wordpress/create-block ツールをリリースしました。これは、Gutenberg ブロックを作成するための公式のゼロ設定ツールです。
前回の記事で@wordpress/create-block
について詳しく説明したので、ここですぐにセットアップを開始できます。
コマンド ライン ツールで、 /wp-content/pluginsフォルダーに移動します。
そこに来たら、次のコマンドを実行します。
npx @wordpress/create-block
@wordpress/create-block
パッケージをインストールする準備ができました。
確認するには、 y
と入力して Enter キーを押します。
これにより、プラグインの PHP、SCSS、および JS ファイルがインタラクティブ モードで生成されます。
以下は、この例で使用する詳細です。 好みに応じて、これらの詳細を自由に変更してください。
Enter キーを押すと、プラグインがダウンロードされて構成されます。
このプロセスには数分かかる場合があります。 完了すると、次の画面が表示されます。
プラグイン ディレクトリ内から実行できるコマンドのリストが表示されます。
-
$ npm start
– 開発用のビルドを開始します。 -
$ npm run build
– 本番用のコードをビルドします。 -
$ npm run format
– ファイルをフォーマットします。 -
$ npm run lint:css
– Lint CSS ファイル。 -
$ npm run lint:js
– lint JavaScript ファイル。 -
$ npm run packages-update
– WordPress パッケージを最新バージョンに更新します。
さて、次のコマンドでプラグイン ディレクトリに移動します。
cd author-plugin
そして、開発ビルドを開始します:
npm start
次に、WordPress ダッシュボードのプラグイン画面に移動し、作成者ボックスプラグインを有効にします。
これで、プラグインが正しく機能しているかどうかを確認できます。 新しい投稿を作成し、 /
と入力してクイック インサーターを起動します。
ウィジェットカテゴリの下のブロック インサーターにも作成者ボックスブロックがあります。 ブロックを選択してエディター キャンバスに追加します。
あなたは終わった。 投稿を保存し、ページをプレビューして、ブロックが正しく表示されるかどうかを確認します。
ブロック足場
ブロックの足場については、前回の記事で取り上げました。 したがって、ここでは、例のために変更するファイルの簡単な概要のみを提供します。
ルート フォルダー
ルート フォルダーには、メインの PHP ファイルといくつかのサブフォルダーがあります。
著者-plugin.php
デフォルトでは、 @wordpress/create-block
パッケージは次の PHP ファイルを提供します。
/** * Plugin Name: Author box * Description: An example block for Kinsta readers * Requires at least: 5.8 * Requires PHP: 7.0 * Version: 0.1.0 * Author: Carlo * License: GPL-2.0-or-later * License URI: https://www.gnu.org/licenses/gpl-2.0.html * Text Domain: author-plugin * * @package author-box */ /** * Registers the block using the metadata loaded from the `block.json` file. * Behind the scenes, it registers also all assets so they can be enqueued * through the block editor in the corresponding context. * * @see https://developer.wordpress.org/reference/functions/register_block_type/ */ function author_box_author_plugin_block_init() { register_block_type( __DIR__ . '/build' ); } add_action( 'init', 'author_box_author_plugin_block_init' );
見出しには、セットアップ時に入力した詳細が表示されます。
静的ブロックでは、ほとんどの場合、 srcフォルダーにある JavaScript ファイルで作業します。 動的ブロックでは、フロント エンドにブロックのコンテンツを表示するための PHP コードを記述します。
srcフォルダー
srcフォルダーは開発フォルダーです。 ここには、次のファイルがあります。
- block.json
- index.js
- edit.js
- save.js
- editor.scss
- スタイル.scss
block.json
block.jsonはメタデータ ファイルです。 @wordpress/create-block
は、次のblock.jsonファイルを生成します。
{ "$schema": "https://schemas.wp.org/trunk/block.json", "apiVersion": 2, "name": "author-box/author-plugin", "version": "0.1.0", "title": "Author box", "category": "widgets", "icon": "businessperson", "description": "An example block for Kinsta readers", "supports": { "html": false }, "textdomain": "author-plugin", "editorScript": "file:./index.js", "editorStyle": "file:./index.css", "style": "file:./style-index.css" }
一般的なblock.jsonファイルの詳細については、以前のブログ投稿を参照してください。
index.js
index.jsファイルは、クライアントでブロック タイプを登録する場所です。
import { registerBlockType } from '@wordpress/blocks'; import './style.scss'; import Edit from './edit'; import save from './save'; registerBlockType('author-box/author-plugin', { edit: Edit, save, });
edit.js
edit.jsファイルは、エディターでレンダリングされるブロック インターフェースを構築する場所です。
import { __ } from '@wordpress/i18n'; import { useBlockProps } from '@wordpress/block-editor'; import './editor.scss'; export default function Edit() { return ( <p {...useBlockProps()}> {__('Author box – hello from the editor!', 'author-plugin')} </p> ); }
save.js
save.jsファイルには、データベースに保存されるブロック コンテンツを構築するスクリプトが含まれています。 このチュートリアルでは、このファイルは使用しません。
import { __ } from '@wordpress/i18n'; import { useBlockProps } from '@wordpress/block-editor'; export default function save() { return ( <p {...useBlockProps.save()}> {__('Author box – hello from the saved content!', 'author-plugin')} </p> ); }
エディタでレンダリングするブロックを構築する
Visual Studio Code または任意のコード エディターでプロジェクトを開きます。
Visual Studio Code を使用している場合は、 Terminal -> New Terminalに移動します。 これにより、プロジェクトのルート フォルダーでターミナル ウィンドウが起動します。
ターミナル (または任意のコマンド ライン ツール) で、次のコマンドを入力します。
npm start
ノード環境を開発モードで実行しています。
ここからは、2 つの異なるルートをたどることになります。 エディターでブロックをレンダリングするには、 edit.jsファイルで作業します。 フロントエンドでブロックをレンダリングするには、メインのプラグイン ファイルに PHP コードを記述する必要があります。
コーディングが始まるので、袖をまくり上げてください。
ブロックをサーバーに登録する
まず、サーバーにブロックを登録し、PHP コードを記述してデータベースからデータを取得する必要があります。
author-plugin.phpファイルでは、2 番目の引数をregister_block_type
関数に渡す必要があります。
function author_box_author_plugin_block_init() { register_block_type( __DIR__ . '/build', array( 'render_callback' => 'author_box_author_plugin_render_author_content' ) ); } add_action( 'init', 'author_box_author_plugin_block_init' );
2 番目の引数は、ブロック タイプを登録するための引数の配列です (使用可能な引数の完全なリストについては、こちらを参照してください)。 上記のコードでは、ブロックを画面にレンダリングするコールバック関数を決定するrender_callback
のみを提供しています。
次に、関数を宣言します。
function author_box_author_plugin_render_author_content() { return 'Hello World!'; }
ファイルを保存し、新しい投稿またはページを作成して、作成者ボックスブロックをエディター キャンバスに追加します。
edit.jsファイルをまだ変更していないため、ブロック エディターにはまだスターター ブロックが表示されています。
しかし、フロントエンドで投稿をプレビューすると、元のブロック コンテンツが "Hello World" 文字列に置き換えられていることがわかります。
現在、フロントエンドでレンダリングされる HTML は PHP ファイルによって生成されるため、 save
関数が何かを返す必要はありません。 それでは、 save.jsファイルに直接移動して、以下に示すようにコードを変更しましょう。
export default function save() { return null; }
ブロック属性を定義する
次に、ユーザー設定を保存する場所が必要です。 たとえば、データベースから取得する投稿アイテムの数、指定したフィールドを表示するかどうかなどです。これを行うには、 block.jsonファイルでいくつかのattributes
を定義します。
たとえば、ブロックに含める投稿の数を決定する機能、主要な画像、日付、抜粋を表示するオプション、および/または著者のプロフィール写真を非表示/表示するオプションをユーザーに与えることができます。
サンプル ブロックを作成するために使用する属性の完全なリストを次に示します。
{ ... "attributes": { "numberOfItems": { "type": "number", "default": 3 }, "columns": { "type": "number", "default": 1 }, "displayDate": { "type": "boolean", "default": true }, "displayExcerpt": { "type": "boolean", "default": true }, "displayThumbnail": { "type": "boolean", "default": true }, "displayAuthorInfo": { "type": "boolean", "default": true }, "showAvatar": { "type": "boolean", "default": true }, "avatarSize": { "type": "number", "default": 48 }, "showBio": { "type": "boolean", "default": true } } }
エディタでレンダリングするブロックを構築する
getEntityRecords
セレクターは@wordpress/data
パッケージに含まれています。 これを使用するには、そのパッケージからuseSelect
フックをedit.js
ファイルにインポートする必要があります。
import { useSelect } from '@wordpress/data';
次に、次のコードをEdit()
関数に追加します。
const posts = useSelect( ( select ) => { return select( 'core' ).getEntityRecords( 'postType', 'post', { 'per_page': 3 }); });
上記のコードでは、投稿数をハードコーディングしました。 ただし、別の数の投稿を設定する機能をユーザーに提供したい場合があります。 そのために属性を使用できます。
block.jsonでnumberOfItems
属性を定義する必要があります。 以下に示すように、 Edit
機能で使用できます。
export default function Edit( { attributes } ) { const { numberOfItems } = attributes; const posts = useSelect( ( select ) => { return select( 'core' ).getEntityRecords( 'postType', 'post', { 'per_page': numberOfItems }); }); console.log( posts ); return ( ... ); }
画面にはまだ投稿が表示されませんが、 console.log
を実行して、ブラウザー インスペクターのコンソールで何が起こるかを確認してください。
useSelect
は、インライン コールバックと依存関係の配列の 2 つの引数を取ることができます。 どちらも、依存関係の 1 つが変更された場合にのみ変更されるメモ化されたバージョンのコールバックを返します。
したがって、 numberOfItems
属性が変更されるたびに投稿を再取得するには、以下に示すようにEdit
関数を変更する必要があります。
export default function Edit( { attributes } ) { const { numberOfItems } = attributes; const posts = useSelect( ( select ) => { return select( 'core' ).getEntityRecords( 'postType', 'post', { 'per_page': numberOfItems }); }, [ numberOfItems ] ); console.log(posts); return ( ... ); }
次に、投稿のリストをレンダリングする必要があります。 これを行うには、組み込みの JavaScript map
メソッドを使用できます。
export default function Edit( { attributes } ) { const { numberOfItems } = attributes; const posts = useSelect( ( select ) => { return select( 'core' ).getEntityRecords( 'postType', 'post', { 'per_page': numberOfItems }); }, [ numberOfItems ] ); console.log(posts); return ( <div { ...useBlockProps() }> <ul> { posts && posts.map( ( post ) => { return ( <li key={ post.id }> <h5> <a href={ post.link }> { post.title.rendered ? post.title.rendered : __( 'Default title', 'author-plugin' ) } </a> </h5> </li> ) })} </ul> </div> ); }
最初に、配列に少なくとも 1 つの投稿があるかどうかを確認し、次にループを実行します。
React コンポーネントでmap
メソッドを使用しているため、現在のリスト項目に投稿 ID を割り当てるためにkey
属性も使用していることに注意してください。
post.link
とpost.title.rendered
は、投稿の URL とタイトルをそれぞれレンダリングします。
下の画像は、 post
オブジェクトのプロパティの完全なリストを示しています。
上記のコードはgetEntityRecords
の基本的な使用例です。 今こそ、私たちの知識を実践に移す時です。
ブロックが、ユーザーが投稿タイトルに追加した可能性のある HTML タグをレンダリングしないようにしたいとします。 WordPress はそのためのRawHTML
コンポーネントを提供します。
まず、@wordpress/element パッケージからコンポーネントをインポートします。
import { RawHTML } from '@wordpress/element';
次に、投稿のタイトルをRawHTML
要素内にラップします。
<div { ...useBlockProps() }> <ul> { posts && posts.map((post) => { return ( <li key={ post.id }> <h5> <a href={ post.link }> { post.title.rendered ? ( <RawHTML> { post.title.rendered } </RawHTML> ) : ( __( 'Default title', 'author-plugin' ) )} </a> </h5> </li> ) })} </ul> </div>
以上です。 投稿のタイトルに HTML タグを追加して、投稿を保存します。 次に、 RawHTML
を使用する場合と使用しない場合でコードをテストし、ブロックのコンテンツが画面上でどのように変化するかを確認します。
日付を追加
WordPress は、日付を管理およびフォーマットするための多数の JavaScript 関数を提供します。 これらの関数を使用するには、最初にedit.jsファイルの@wordpress/date
パッケージからインポートする必要があります。
import { dateI18n, format, __experimentalGetSettings } from '@wordpress/date';
-
dateI18n
: 日付をフォーマットし、サイトのロケールに変換します。 -
format
: 日付をフォーマットします。 -
__experimentalGetSettings
: WordPress の一般設定で設定された形式で日付を表示します。
これらの関数は文書化されていませんが、いくつかのブロックのソース コードで役立つ例を見つけることができます。 たとえば、latest-posts および post-date edit.jsファイルを参照してください。
次に、 displayDate
属性を追加します。
const { numberOfItems, displayDate } = attributes;
次に、 <li>
要素内に次のコードを追加します。
{ displayDate && ( <time className='wp-block-author-box-author-plugin__post-date' dateTime={ format( 'c', post.date_gmt ) } > { dateI18n( __experimentalGetSettings().formats.date, post.date_gmt )} </time> ) }
そこで何が起こるの?
-
displayDate
がtrue
場合、time
要素を使用して日付を表示します。 -
dateTime
属性は、許可された形式のいずれかで要素の時刻および/または日付を提供します。 -
dateI18n
は、ローカライズされた形式で日付を取得します。 この関数は、PHPPHP のdate_i18n
WordPress 関数と同様に機能します。
抜粋を追加
これで、投稿の抜粋を簡単に追加できるはずです。 まず、ブラウザーのインスペクターでexcerpt
プロパティを見てください。 実際のコンテンツはexcerpt.rendered
に格納されていることがわかります。
次に、 displayExcerpt
属性をattributes
オブジェクトに追加します。
const { numberOfItems, displayDate, displayExcerpt } = attributes;
次に、 Edit
関数の</li>
終了タグの前に次のコードを追加します。
{ displayExcerpt && post.excerpt.rendered && ( <p> <RawHTML> { post.excerpt.rendered } </RawHTML> </p> ) }
JavaScript に慣れていない場合は、ここと上記でShort Circuit Evaluationを使用しました。これにより、すべての条件が true の場合、最後のオペランドの値が返されます (詳しくは、論理 && 演算子と論理 AND (&& を使用したインライン If) を参照してください)。 )))。
最後に、コードをもう一度テストできます。 block.jsonファイルの属性値を変更し、エディターで何が起こるかを確認します。
アイキャッチ画像を追加する
ここで、注目の画像をレンダリングするコードを追加する必要があります。 attributes へのdisplayThumbnail
属性の追加を開始しattributes
。
const { numberOfItems, displayDate, displayExcerpt, displayThumbnail } = attributes;
ここで、注目の画像がどこに保存されているかを把握する必要があります。 上で述べたように、注目の画像を取得するには、クエリに新しい_embed
引数を追加する必要があります。 コードに戻り、クエリ引数を次のように変更します。
const posts = useSelect( ( select ) => { return select( 'core' ).getEntityRecords( 'postType', 'post', { 'per_page': numberOfItems, '_embed': true }); }, [ numberOfItems ] );
ここでは、 '_embed': true
を引数の配列に追加しただけです。 これは、注目の画像を表示するために必要な画像の詳細を提供する_embedded
プロパティを含むpost
オブジェクトを提供します。
これで、画像の詳細を見つける場所がわかったはずです。
画面に画像をレンダリングするコードを追加するだけです。
{ displayThumbnail && post._embedded && post._embedded['wp:featuredmedia'] && post._embedded['wp:featuredmedia'][0] && <img className='wp-block-author-box-author-plugin__post-thumbnail' src={ post._embedded['wp:featuredmedia'][0].media_details.sizes.medium.source_url } alt={ post._embedded['wp:featuredmedia'][0].alt_text } /> }
ファイルを保存し、ブロック エディターに切り替えて、 displayThumbnail
属性がtrue
に設定されているときに画像が正しく表示されるかどうかを確認します。
サイドバー コントロールを追加する
これまでのところ、 block.jsonで設定された属性のデフォルト値を使用してきました。 しかし、前回の記事から、イベント ハンドラーを定義して、ユーザーが各属性にカスタム値を割り当てることができることがわかりました。
これを行うには、一連のコントロールをブロック設定サイドバーに追加します。 edit.jsで、対応するパッケージから次のコンポーネントをインポートします。
import { useBlockProps, InspectorControls } from '@wordpress/block-editor'; import { PanelBody, PanelRow, QueryControls, ToggleControl, RangeControl } from '@wordpress/components';
-
InspectorControls
: ブロック全体に影響するサイドバー設定が含まれています (GitHub を参照)。 -
PanelBody
: 折りたたみ可能なコンテナーを設定サイドバーに追加します (GitHub を参照)。 -
PanelRow
: サイドバー コントロールの汎用コンテナーを生成します (GitHub を参照)。 -
QueryControls
: クエリを作成するための設定コントロールを提供します (GitHub を参照)。 -
ToggleControl
: ユーザーが特定のオプションを有効/無効にするトグル ボタンを提供します (GitHub を参照)。 -
RangeControl
: 増分値の範囲から選択するために使用されます (GitHub を参照)。
次に、 Edit
機能を更新して、現在使用可能なコントロールを使用する必要があります。 まず、 Edit
機能を次のように変更します。
export default function Edit( { attributes, setAttributes } ) { const { numberOfItems, columns, displayExcerpt, displayDate, displayThumbnail } = attributes; const posts = useSelect( ( select ) => { return select( 'core' ).getEntityRecords( 'postType', 'post', { 'per_page': numberOfItems, '_embed': true }); }, [ numberOfItems ] ); ... }
Edit
関数に渡されるsetAttributes
プロパティに注意してください。
これで、対応する要素を JSX コードに追加できます。
return ( <> <InspectorControls> <PanelBody title={ __( 'Content Settings', 'author-plugin' ) }> <PanelRow> <QueryControls numberOfItems={ numberOfItems } onNumberOfItemsChange={ ( value ) => setAttributes( { numberOfItems: value } ) } minItems={ 1 } maxItems={ 10 } /> </PanelRow> <PanelRow> <RangeControl label={ __( 'Number of Columns', 'author-plugin' ) } value={ columns } onChange={ ( value ) => setAttributes( { columns: value } ) } min={ 1 } max={ 4 } required /> </PanelRow> <PanelRow> <ToggleControl label={ __( 'Show Featured Image', 'author-plugin' ) } checked={ displayThumbnail } onChange={ () => setAttributes( { displayThumbnail: ! displayThumbnail } ) } /> </PanelRow> <PanelRow> <ToggleControl label={ __( 'Show Date', 'author-plugin' ) } checked={ displayDate } onChange={ () => setAttributes( { displayDate: ! displayDate } ) } /> </PanelRow> <PanelRow> <ToggleControl label={ __( 'Display Excerpt', 'author-plugin' ) } checked={ displayExcerpt } onChange={ () => setAttributes( { displayExcerpt: ! displayExcerpt } ) } /> </PanelRow> </PanelBody> </InspectorControls> <div { ...useBlockProps() }> ... </div> </> );
うわー、それはたくさんのコードですね。 しかし、それは非常に簡単に理解できます。
ここで注目すべき要素属性は、 QueryControls
のonNumberOfItemsChange
と、 RangeControl
およびonChange
のToggleControl
です。 これらの属性は、ユーザーがブロックの外観や動作をカスタマイズできるようにするために必要なイベント ハンドラーを設定します。
また、React フラグメントを宣言するための短い構文である<>
および</>
タグを使用したことにも気付くでしょう。
次に、ファイルを保存し、エディターに移動して、ページを更新します。
すべて入っていますか? 次に、投稿者の詳細を追加します。
投稿者を探す
上で述べたように、ブロックは現在の投稿と同じ著者によって書かれた記事のリストを表示します。
投稿者の ID を取得するには、 core/editor
データストアからgetCurrentPostAttribute
セレクターをインポートします。
wp.data.select( 'core/editor' ).getCurrentPostAttribute( 'author' )
getCurrentPostAttribute
は、保存された投稿の属性値を返します。
作成者 ID を取得したら、次のようにクエリを変更できます。
const posts = useSelect( ( select ) => { const _authorId = select( 'core/editor' ).getCurrentPostAttribute( 'author' ); return select( 'core' ).getEntityRecords( 'postType', 'post', { 'author': _authorId, 'per_page': numberOfItems, '_embed': true }); }, [ numberOfItems ] );
このコードを使用すると、現在の投稿と同じ著者によるn
の記事のリストを取得できます。
作成者 ID を取得したので、それを使用してデータベースから追加のデータをフェッチすることもできます。
著者の詳細を表示
利用可能なドキュメントがないため、コアの Post Author ブロックのコードを参照として使用しました。
作成者の詳細を表示するには、最初に新しい依存関係をインポートする必要があります。
import { forEach } from 'lodash';
次に、 Edit
機能で、 attributes
オブジェクトを次のように更新します。
const { numberOfItems, columns, displayExcerpt, displayDate, displayThumbnail, displayAuthorInfo, showAvatar, avatarSize, showBio } = attributes;
完了したら、前のセクションで見たコードを編集して、著者の詳細を取得します。
const { authorDetails, posts } = useSelect( ( select ) => { const _authorId = select( 'core/editor' ).getCurrentPostAttribute( 'author' ); const authorDetails = _authorId ? select( 'core' ).getUser( _authorId ) : null; const posts = select( 'core' ).getEntityRecords( 'postType', 'post', { 'author': _authorId, 'per_page': numberOfItems, '_embed': true }); return { authorDetails: authorDetails, posts: posts }; }, [ numberOfItems ] );
作成者の詳細を取得するためにgetUser
セレクターを使用したことに注意してください。
次に、作成者のアバターを取得することができます。 以下のコードは、アバターの URL とサイズを格納するアイテムの配列を作成します。
const avatarSizes = []; if ( authorDetails ) { forEach( authorDetails.avatar_urls, ( url, size ) => { avatarSizes.push( { value: size, label: `${ size } x ${ size }`, } ); } ); }
次に、サイドバー パネルとコントロールを追加して、ユーザーがブロック内の作成者の領域をカスタマイズできるようにします。
return ( <> <InspectorControls> <PanelBody title={ __( 'Author Info', 'author-plugin' ) }> <PanelRow> <ToggleControl label={ __( 'Display Author Info', 'author-plugin' ) } checked={ displayAuthorInfo } onChange={ () => setAttributes( { displayAuthorInfo: ! displayAuthorInfo } ) } /> </PanelRow> { displayAuthorInfo && ( <> <PanelRow> <ToggleControl label={ __( 'Show avatar' ) } checked={ showAvatar } onChange={ () => setAttributes( { showAvatar: ! showAvatar } ) } /> { showAvatar && ( <SelectControl label={ __( 'Avatar size' ) } value={ avatarSize } options={ avatarSizes } onChange={ ( size ) => { setAttributes( { avatarSize: Number( size ), } ); } } /> ) } </PanelRow> <PanelRow> <ToggleControl label={ __( 'Show Bio', 'author-plugin' ) } checked={ showBio } onChange={ () => setAttributes( { showBio: ! showBio } ) } /> </PanelRow> </> ) } </PanelBody> ... </InspectorControls> ... </> );
以下の画像は、更新された設定サイドバーを示しています。
最後に、著者のセクションをブロックに追加できます。
return ( <> <InspectorControls> ... </InspectorControls> <div { ...useBlockProps() }> { displayAuthorInfo && authorDetails && ( <div className="wp-block-author-box-author-plugin__author"> { showAvatar && ( <div className="wp-block-author-box-author-plugin__avatar"> <img width={ avatarSize } src={ authorDetails.avatar_urls[ avatarSize ] } alt={ authorDetails.name } /> </div> ) } <div className='wp-block-author-box-author-plugin__author-content'> <p className='wp-block-author-box-author-plugin__name'> { authorDetails.name } </p> { showBio && // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Optional_chaining authorDetails?.description && authorDetails.description.length > 0 && ( <p className='wp-block-author-box-author-plugin__description'>{ authorDetails.description }</p> ) } </div> </div> )} <ul> ... </ul> </div> </> );
次の画像は、画面にどのようにレンダリングされるかを示しています。
edit.jsファイルを保存して、テストを実行します。 ブロックの設定に応じて、ブロックにはさまざまな要素を含める必要があります。
最後にもう 1 つ欠けていることがあります。それは、記事を表示する列の数です。
列数を変更する
ユーザーが記事のプレビューを列に表示できるようにするために、 block.jsonファイルでcolumns
属性を定義しました。 また、スクリプトにcolumns
属性を含め、ユーザーが列数を変更できるように設定コントロールを作成しましたが、この変更は現時点では効果がありません。
上記の JSX コードでは、いくつかの要素に CSS クラスを追加したことに気付いたはずです。
Author セクションの要素に割り当てられるクラス:
-
wp-block-author-box-author-plugin__author
-
wp-block-author-box-author-plugin__avatar
-
wp-block-author-box-author-plugin__author-content
-
wp-block-author-box-author-plugin__name
-
wp-block-author-box-author-plugin__description
コンテンツ セクションの要素に割り当てられるクラス:
-
wp-block-author-box-author-plugin__post-items
-
wp-block-author-box-author-plugin__post-thumbnail
-
wp-block-author-box-author-plugin__post-title
-
wp-block-author-box-author-plugin__post-date
-
wp-block-author-box-author-plugin__post-excerpt
まだ1クラス足りない。 このクラスの名前は、ユーザーが設定した列の数を反映して動的に生成されます。
Edit.js
ファイルに戻り、 ul
要素を次のように変更します。
<ul className={ `wp-block-author-box-author-plugin__post-items columns-${ columns }` }> ... </ul>
文字列内に式を挿入するために、テンプレート リテラル構文に従って、新しいcolumns-${ columns }
クラスを追加しました。 このように、 ul
要素に付加された属性は、ユーザー設定 (たとえば、 columns-1
、 columns-2
など) に依存します。
style.scss
ファイルを開き、既存のコードを次のコードに置き換えます。
.wp-block-author-box-author-plugin { background-color: #21759b; color: #fff; padding: .6em; ul.wp-block-author-box-author-plugin__post-items { padding: 0; list-style-type: none; display: grid; gap: .5em; @for $i from 2 through 4 { &.columns-#{ $i } { grid-template-columns: repeat(#{ $i }, 1fr); } } li { list-style: none; img.wp-block-author-box-author-plugin__post-thumbnail { height: auto; max-width: 100%; } } } } .wp-block-author-box-author-plugin__author { display: flex; flex-wrap: wrap; } .wp-block-author-box-author-plugin__avatar { margin-right: 1em; } .wp-block-author-box-author-plugin__author-content { flex-basis: 0; flex-grow: 1; }
この記事の範囲を超えているため、そのコードについては深く掘り下げません。 ただし、さらに深く掘り下げたい場合は、次のリソースを参照できます。
- CSS グリッド レイアウト
- CSS グリッドを学ぶ
- Sass の @for ルール
- Sass でのネスト
以上で、エディタでのブロックのレンダリングは終了です。
ページ上でレンダリングするブロックの構築
エディターでブロックをレンダリングするコードが完成したので、次に進み、フロント エンドでレンダリングするブロックを作成します。
前に述べたように、動的ブロックに関しては、プラグイン ファイルは、フロント エンドでレンダリングされる HTML を生成する責任があります。
そのため、プラグインのメイン ファイル (この例ではauthor-plugin.php ) を開きます。
最初に行うことは、ブロック属性を WordPress PHP 関数で使用できるようにすることです。 PHP ファイルで、関数定義を次のように変更します。
function author_box_author_plugin_render_author_content( $attr ) { ... }
これで、WordPress 関数を使用してデータを取得および操作できるようになりました。 たとえば、 get_posts
を使用して最新のブログ投稿を取得できます ( get_posts
関数について詳しくは、こちらの記事を参照してください)。
function author_box_author_plugin_render_author_content( $attr ) { $args = array( 'numberposts' => $attr['numberOfItems'], ); $my_posts = get_posts( $args ); if( ! empty( $my_posts ) ){ $output = '<ul>'; foreach ( $my_posts as $p ){ $output .= '<li><a href="' . esc_url( get_permalink( $p->ID ) ) . '">' . $p->post_title . '</a></li>'; } $output .= '</ul>'; } return $output ?? '<strong>Sorry. No posts matching your criteria!</strong>'; }
上記の関数は、WordPress データベースから最新のnumberOfItems
ブログ投稿を取得し (デフォルトではpost_type
はpost
に設定されています)、 $post
オブジェクトの配列を返します。 配列を反復処理してリスト項目を構築します。
HTML 出力を調べると、次の画像に示すような投稿の単純なリストであることがわかります。
前回の記事で、 useBlockProps
React フックを使用して、JSX コードでブロックのラッパー要素をマークすると述べました。 PHP 関数でも同じことを行う必要があります。
WordPress はそのためのget_block_wrapper_attributes
関数を提供します。
したがって、PHP コードを次のように変更します。
function author_box_author_plugin_render_author_content( $attr ) { $args = array( 'numberposts' => $attr['numberOfItems'] ); $my_posts = get_posts( $args ); if( ! empty( $my_posts ) ){ $output = '<div ' . get_block_wrapper_attributes() . '>'; $output .= '<ul>'; foreach ( $my_posts as $p ){ $title = $p->post_title ? $p->post_title : 'Default title'; $url = esc_url( get_permalink( $p->ID ) ); $output .= '<li>'; $output .= '<a href="' . $url . '">' . $title . '</a>'; $output .= '</li>'; } $output .= '</ul>'; $output .= '</div>'; } return $output ?? '<strong>Sorry. No posts matching your criteria!</strong>'; }
wp-block-author-box-author-plugin
クラスがコンテナー要素に割り当てられ、ブロックの背景色が異なります。
次に、 get_posts
関数がWP_Posts
データを取得し、 foreach
サイクルがリスト項目を作成します (get_posts が返すデータを表示する方法も参照してください)。
アイキャッチ画像、日付、抜粋を追加
次に、投稿のサムネイル、日付、抜粋を追加する必要があります。 同じファイルで、PHP コードを次のように変更します。
function author_box_author_plugin_render_author_content( $attr ) { $args = array( 'numberposts' => $attr['numberOfItems'] ); $my_posts = get_posts( $args ); if( ! empty( $my_posts ) ){ $output = '<div ' . get_block_wrapper_attributes() . '>'; $output .= '<ul class="wp-block-author-box-author-plugin__post-items columns-">'; foreach ( $my_posts as $p ){ $title = $p->post_title ? $p->post_title : 'Default title'; $url = esc_url( get_permalink( $p->ID ) ); $thumbnail = has_post_thumbnail( $p->ID ) ? get_the_post_thumbnail( $p->ID, 'medium' ) : ''; $output .= '<li>'; if( ! empty( $thumbnail ) && $attr['displayThumbnail'] ){ $output .= $thumbnail; } $output .= '<h5><a href="' . $url . '">' . $title . '</a></h5>'; if( $attr['displayDate'] ){ $output .= '<time datetime="' . esc_attr( get_the_date( 'c', $p ) ) . '">' . esc_html( get_the_date( '', $p ) ) . '</time>'; } if( get_the_excerpt( $p ) && $attr['displayExcerpt'] ){ $output .= '<p>' . get_the_excerpt( $p ) . '</p>'; } $output .= '</li>'; } $output .= '</ul>'; $output .= '</div>'; } return $output ?? '<strong>Sorry. No posts matching your criteria!</strong>'; }
foreach
ループは$my_posts
配列を反復処理します。 各反復で、いくつかの条件が属性値をチェックし、それに応じて出力を構築します。
次に、画面上の出力を見てください。
これで、テストを実行できます。 日付、抜粋、サムネイルの設定を変更し、フロントエンドでブロック コンテンツがどのように変化するかを確認します。
投稿を列に表示する
JavaScript コードでは、 columns-${ columns }
クラスを使用して、投稿のプレビューを列に表示しました。 次に、PHP で同じことを行う必要があります。
これを行うには、次の 2 行のコードを追加するだけです。
$num_cols = $attr['columns'] > 1 ? strval( $attr['columns'] ) : '1'; $output .= '<ul class="wp-block-author-box-author-plugin__post-items columns-' . $num_cols . '">';
これにより、投稿のプレビューを含むul
要素にcolumns-n
クラスが追加されます。 ページに表示される列の数は、ブロック設定で設定された列の数と一致するはずです。
著者ボックスを構築する
最後に、アバター、名前、説明など、作成者の詳細を含むボックスを作成する必要があります。
コールバック関数内で、各属性の現在の値を確認する一連の条件を追加する必要があります。
if( $attr['displayAuthorInfo'] ){ $output .= '<div class="wp-block-author-box-author-plugin__author">'; if( $attr['showAvatar'] ){ $output .= '<div class="wp-block-author-box-author-plugin__avatar">' . get_avatar( get_the_author_meta( 'ID' ), $attr['avatarSize'] ) . '</div>'; } $output .= '<div class="wp-block-author-box-author-plugin__author-content">'; $output .= '<div class="wp-block-author-box-author-plugin__name">' . get_the_author_meta( 'display_name' ) . '</div>'; if( $attr['showBio'] ){ $output .= '<div class="wp-block-author-box-author-plugin__description">' . get_the_author_meta( 'description' ) . '</div>'; } $output .= '</div>'; $output .= '</div>'; }
コードは非常に簡単です。 各属性の現在の値をチェックし、 true
場合は必要な HTML を生成します。
次に、PHP ファイルを保存し、エディターのブロックとフロント エンドの同じブロックを比較します。
サンプル ブロックの完全なコードは、このパブリック Gist にあります。
動的ブロック開発の推奨リソース
この記事を読んで耳を澄ませ、グーテンベルグ ブロックの作成方法を学ぶことで専門能力開発の機会が得られることに気づき始めた場合は、ブロック開発の背後にあるテクノロジの新しいスキルを探求し、習得し続けることをお勧めします。
信頼できる公式ドキュメントはまだありませんが、無料と有料の優れたリソースが存在するため、この記事を書いているときに参考にしました. 利用可能な多くのリソースの中で、以下をお勧めします。
公式リソース
- データ
- コアデータ
- ダイナミック ブロックの作成
- Gutenberg ブロック開発の概要
- MeetUp での WordPress ソーシャル学習
WordPress コアコントリビューターからの推奨チュートリアル
- Ryan Welcher (@ryanwelcher) による getEntityRecords を使用した Gutenberg でのデータの要求
- Darren Ethier (@nerrad) による @wordpress/data API の実用的な概要
JavaScript、React、Redux のリソース
- MDN による JavaScript チュートリアル
- React 入門 (公式)
- Redux チュートリアル (公式)
Kinstaの関連リソース
- JavaScript とはWeb で最も人気のあるスクリプト言語の概要
- JavaScript でのエラー処理の決定版ガイド
- Node.js とは何か、それを使用する理由
- Windows、macOS、Linux に Node.js と npm をインストールする方法
- 複数のツールを使用して Node.js コードをデバッグする方法
- Node.js と PHP: 直接比較
- 2022 年に最も人気のある 10 種類の Node.js アプリ
- Angular と React: 詳細な比較
概要
Gutenberg ブロックの開発を通じて、この (2 回目の) 長い旅の終わりに到達しました。
この記事では、アプリケーションの状態や Redux ストアなど、いくつかの高度なトピックについて説明しました。 しかし、これでブロック開発全般についての理解が深まったことを願っています。
はい、Node.js、Webpack、Babel、React、および Redux のスキルは、高度な Gutenberg ブロックを構築する際に不可欠ですが、始めるために React 忍者である必要はありません。 Gutenberg ブロックの開発方法を学ぶことは、必ずしも複雑である必要はありません。 正しい動機で、適切な学習パスに従ってください。
そして、この記事 (および前の記事) が、道筋を見つけてすぐに Gutenberg 開発を開始するための正しいマップを提供することを願っています。
あなた次第! 動的ブロックを作成しましたか? 私たちと共有できる例はありますか? また、これまでの経験で最大のハードルは何でしたか? 以下にコメントを残してください。