Gutenberg InnerBlocks で優れた WordPress 編集エクスペリエンスを作成し、時間を節約する

公開: 2023-02-12

繰り返さないで

開発者にとって、怠惰は美徳です。 よくできた再利用可能なコンポーネントは時間を節約し、効率的な再利用と一貫性を可能にします。 これは、WordPress で編集エクスペリエンスを作成するのに適しています。一貫性があると、Web サイトを日常的に使用する人に親しみと知識が生まれます。

WordPress は、現在単に「The Editor」として知られている Gutenberg ブロックエディターのリリースで多くの騒ぎを起こしました。 コンテンツの編集、下書き、および公開については、古い WYSIWYG よりもはるかに優れた優れたエクスペリエンスを提供します。 開発者として、私はクライアントに最高の編集エクスペリエンスを提供したいと考えています。コア機能を活用したいと考えており、車輪の再発明はしたくありません。 幸いなことに、WordPress では、これらすべてをカスタム ブロックで行うことができます。

InnerBlocks を入力してください

InnerBlocks は、WordPress エディターの優れた機能です。 開発者は、段落、見出し、ボタンなどのコア ブロックを使用して、クライアントに一貫したエクスペリエンスを作成できます。 テキスト セクションを書き直してフィールドを再宣言する代わりに、クライアントは慣れ親しんだエクスペリエンスを得ることができます。 同じブロックの編集と結合。 クライアントのために構築する必要があるかもしれないブロックを見て、InnerBlocks がそれを達成するのにどのように役立つかを見てみましょう。

InnerBlocks を使用したブロックの構築

見出し、段落、ボタンのリンクを含む Call to Action ブロックの例
図: Call to Action ブロックの例。 これには、見出し、段落、およびいくつかのボタン リンクが含まれます。

このブロックを調べて、どのように構築するかを考えてみましょう。 ブロックを作成するときに使用する一般的なツールは、Advanced Custom Fields (ACF) です。 ACF Pro はカスタム ブロックのサポートを追加します。これにより、開発者はエディターとフロント エンド用に PHP でブロックを記述できます。 また、カスタム フィールドを使用することもできます。これは、多くの WordPress 開発者が慣れ親しんでいるパラダイムです。 ACF は InnerBlocks をサポートしています。つまり、カスタム ブロックを作成できますが、その見出し、段落、またはボタンのカスタム コードを記述する必要さえありません。

ACF ブロックを使用すると、コア ブロックを活用して、このブロックに表示されるすべてのテキストの優れた編集エクスペリエンスを実現できます。 もう 1 つの考えられるオプションは、ブロック パターンを使用することですが、素晴らしい WordPress エクスペリエンスの開発者およびキュレーターとして、カスタム ブロックを作成することで望ましい目標が達成されます。

ブロック登録コード

カスタム ACF ブロックを登録するコードは次のとおりです。 acf_register_block_type 関数の使用について詳しくは、こちらをご覧ください。

 <?php /** * Template for registering an ACF powered custom block. * * More info: https://www.advancedcustomfields.com/resources/blocks/ */ /** * Register the block. */ add_action( 'acf/init', function() { /** * ACF block registration options here: https://www.advancedcustomfields.com/resources/acf_register_block_type/ */ acf_register_block_type( array( 'name' => 'call-to-action-demo', // JS will register as: acf/{block-name}. 'title' => __( 'Call to Action ACF Demo', 'locale' ), 'description' => __( 'A custom ACF Call to Action block.', 'locale' ), 'render_template' => 'partials/blocks/call-to-action-demo.php', // Change to block template. 'category' => 'design', // Category in the block inserter. 'keywords' => array( 'action', 'buttons', 'cta' ), // Searchable keywords. 'supports' => array( 'align' => false, // Disable support for align. 'anchor' => true, // Enable support for anchor. 'jsx' => true, // Enable support for JSX. 'mode' => false, // Disable ACF block edit/preview mode switching as we are only using InnerBlocks for editable content. ), ) ); } );

コードを分解してみましょう。 acf_register_block_type 関数を使用してブロックを登録し、ブロックを定義して機能のオンとオフを切り替える引数の配列を渡します。

  • 推奨される手順に従って、ブロックに一意の名前を追加し、人間が読めるタイトルと説明を追加していることに注意してください。 後でブロック用の PHP テンプレートを設定するレンダー テンプレートを指定します。 Block Inserter でブロックをグループ化するカテゴリも追加しました。
  • インサーターでブロックを検索しやすくするための検索可能なキーワードがあります。
  • HTML アンカーの設定などの機能を有効にするために「supports」配列を追加し、このブロックは常にページの中央に配置されるため、配置をオフにしました。
  • InnerBlocks マジックをオンにすると、配列がサポートされます。 「jsx」を true に設定すると、ブロック内で React jsx テンプレートのレンダリングをサポートすることが ACF に通知されます。

ブロックに必要なコンテンツを確認しましょう。

  • 見出し
  • 段落テキスト
  • アクションを起こすためのボタン!

ここで概説したように、通常はフィールドをブロックに割り当てます。 ただし、この場合はその必要はありません。コア ブロックを活用して、これらすべてを実現できます。 たとえば、ブロックに画像の背景が必要な場合、ブロックに ACF 画像フィールドを追加すると、それを達成するための優れた方法になる可能性があります。 ただし、ここでは、InnerBlocks の例にとどまり、テンプレートにジャンプしましょう。

ブロック テンプレート

これが新しいブロックのテンプレートです。 ブロック登録がブロック テンプレートの場所を指すようにしてください。 一般的な方法は、これらをテーマのパーシャル フォルダーに配置することです。

 <?php /** * ACF Call to Action example block template. * * More info: https://www.advancedcustomfields.com/resources/acf_register_block_type/ * * @param array $block The block settings and attributes. * @param string $content The block inner HTML (empty). * @param bool $is_preview True during AJAX preview. * @param (int|string) $post_id The post ID this block is saved to. * */ // Create id attribute allowing for custom "anchor" value. $block_ . $block['id']; if ( ! empty( $block['anchor'] ) ) { $block_id = $block['anchor']; } // Create class attribute allowing for custom "className" and "align" values. $class_name = 'acf-call-to-action-demo'; if ( ! empty( $block['className'] ) ) { $class_name .= ' ' . $block['className']; } if ( ! empty( $block['align'] ) ) { $class_name .= ' align' . $block['align']; } ?> <div class="<?php echo esc_html( $class_name ); ?>"> <div class="cta__inner"> <?php // Set up innerBlocks and provide a template. // Restrict InnerBlocks to allowed block list. $allowed_blocks = array( 'core/heading', 'core/paragraph', 'core/buttons' ); // Start InnerBlocks with a template. $template = array( array( 'core/heading', array( 'placeholder' => __( 'CTA Heading', 'locale' ), 'align' => 'center', 'level' => '2', ), ), array( 'core/paragraph', array( 'placeholder' => __( 'Add CTA text here', 'locale' ), 'align' => 'center', ), ), array( 'core/buttons', array( 'placeholder' => __( 'Add CTA buttons here', 'locale' ), 'align' => 'center', ), array( array( 'core/button', array( 'text' => __( 'Take action', 'locale' ), ), ), array( 'core/button', array( 'text' => __( 'Learn more', 'locale' ), ), ), ), ), ); // Echo out our JSX InnerBlocks compoennt for the editor. echo '<InnerBlocks allowedBlocks="' . esc_attr( wp_json_encode( $allowed_blocks ) ) . '" template="' . esc_attr( wp_json_encode( $template ) ) . '" templateLock="false" />'; ?> </div> </div>

このコードを分解してみましょう。

  • 最初に、アンカーやカスタム クラス名のサポートなど、ACF がブロック ガイダンスで提供する汎用ブロック テンプレート ボイラープレートがあります。
  • InnerBlocks コンポーネントはプロパティを受け取ることができます。 このテンプレートでは 3 つ使用しています。
    • 許可されたブロック:キュレートする許可されたブロックの配列を追加します。 これらのブロックのみが、カスタム ブロックの InnerBlocks スペース内で選択できます。
    • テンプレート:ブロックの配列を渡すことができ、ブロックが最初にエディターにロードされるときに開始するブロックのブロック属性を渡すことができます。
      • ブロック属性を渡して、ユーザーを成功に導くことができることに注意してください。 見出しにはすでにレベル 2 が設定されており、段落は中央揃えになっています。
      • 注: コア ブロックは、JavaScript では常に {plugin}/blockname として参照されます。 この場合、コア ブロックを使用していますが、カスタム ACF ブロックを使用する場合は、ブロック名の前に「acf」と記述します。 InnerBlocks を使用する場合、React を使用する WordPress エディターにこのコンポーネントを渡していることを思い出してください。 そのため、ここでは JS で考えています。
      • 別の注意: コア/ボタン ブロックが InnerBlocks 自体を使用していることに注意してください。 実際には、2 つのコア/ボタン ブロックの配列を渡しています。
    • テンプレートのロック: templateLock は InnerBlocks コンポーネントで設定されます。 これを「all」に設定すると、InnerBlocks に提供されたテンプレート内のブロックはどれも移動または削除できませんでした。 「挿入」に設定した場合、ブロック内のブロックは移動のみ可能で、ブロックを削除することはできず、新しいブロックを追加することもできません。 「false」に設定すると、InnerBlocks インスタンスのロックが解除され、親テンプレートのロックに関係なくロックが解除されます (詳細は後述)。 ブロック テンプレートの詳細については、WordPress ブロック エディター ハンドブックをご覧ください。 ブロックロックについては後で説明します。

新しいブロックができました! もちろん、いくつかのスタイリングの後、例のブロックはエディターで次のように表示されます。

見出しブロックが選択された行動喚起ブロック。
図: エディタ内の Call to Action ブロック。 見出しブロックが選択されます。

より深いネスト: ネストされた InnerBlocks を使用してエクスペリエンスをさらにキュレートする

すばらしいブロックができました。テンプレートで WYSIWYG を設定したり、カスタム フィールドを処理したりする必要さえありませんでした。 しかし、このエクスペリエンスをクライアントのためにさらにキュレートして微調整したい場合はどうすればよいでしょうか? 見出しが常に存在することを確認する要求を受け取ったとしましょう。そのため、常に見出しブロックがありますが、その後のコンテンツは柔軟で、リストや別の種類のブロックを含めることさえできます。 私たちの目標は、一貫性を維持しながら、その柔軟性を実現することです。

InnerBlocks を使用する際のルールをいくつか考えてみましょう。

  • 1 つのブロック内に InnerBlocks のインスタンスを 1 つだけ含めることができます。
  • InnerBlocks 内の複数のブロックは、独自の InnerBlocks コンポーネントを使用できます。
  • InnerBlocks は templateLock プロパティを介してロックできますが、ネストされたブロック構造内のより深い InnerBlocks のインスタンスは、templateLock を false に設定することで再度ロック解除できます。

1 つの解決策は、InnerBlocks のラッパーとして機能する新しいブロックを作成することです。 そのブロックを親ブロック テンプレートに含めてロックしますが、「templateLock」を false に設定することで、ラッパー ブロックを明示的にロック解除します。 また、ブロックの親を設定することにより、この特別なラッパー ブロックが選択した親ブロック内でのみ使用できるようにすることもできます。 そのスペース内で複数のブロック タイプが編集者リストなどを提供できるようにする一方で、親の行動喚起ブロックで見出し、ボタン、およびラッパー ブロックのみを許可することもできます。

個々のブロックのロック

WordPress 5.9 の新機能は、テンプレート内の個々のブロックをロックする機能です。 これは、柔軟でありながら一貫性があるという問題に対する別の可能な解決策です。

いくつかの個々のブロックがロックされたテンプレートは次のようになります。

 <?php /** * ACF Call to Action example block template. * * More info: https://www.advancedcustomfields.com/resources/acf_register_block_type/ * * @param array $block The block settings and attributes. * @param string $content The block inner HTML (empty). * @param bool $is_preview True during AJAX preview. * @param (int|string) $post_id The post ID this block is saved to. * */ // Create id attribute allowing for custom "anchor" value. $block_ . $block['id']; if ( ! empty( $block['anchor'] ) ) { $block_id = $block['anchor']; } // Create class attribute allowing for custom "className" and "align" values. $class_name = 'acf-call-to-action-demo'; if ( ! empty( $block['className'] ) ) { $class_name .= ' ' . $block['className']; } if ( ! empty( $block['align'] ) ) { $class_name .= ' align' . $block['align']; } ?> <div class="<?php echo esc_html( $class_name ); ?>"> <div class="cta__inner"> <?php // Set up innerBlocks and provide a template. // Restrict InnerBlocks to allowed block list. $allowed_blocks = array( 'core/heading', 'core/paragraph', 'core/buttons' ); // Start InnerBlocks with a template. $template = array( array( 'core/heading', array( 'placeholder' => __( 'Heading', 'locale' ), 'align' => 'center', 'level' => '2', 'lock' => array( 'move' => true, // Block may nto be moved. 'remove' => true, // Block may not be removed. ), ), ), array( 'core/paragraph', array( 'placeholder' => __( 'Add CTA text here', 'locale' ), 'align' => 'center', ), ), array( 'core/buttons', array( 'placeholder' => __( 'Add CTA buttons here', 'locale' ), 'align' => 'center', 'lock' => array( 'move' => true, // Block may not be moved. 'remove' => true, // Block may not be removed. ), ), array( array( 'core/button', array( 'text' => __( 'Take action', 'locale' ), ), ), array( 'core/button', array( 'text' => __( 'Learn more', 'locale' ), ), ), ), ), ); // Echo out our JSX InnerBlocks compoennt for the editor. echo '<InnerBlocks allowedBlocks="' . esc_attr( wp_json_encode( $allowed_blocks ) ) . '" template="' . esc_attr( wp_json_encode( $template ) ) . '" />'; ?> </div> </div>

見出しとボタン ブロックは移動または削除できなくなります。 テンプレートの変更を取得するには、必ずエディターを更新し、ブロックを削除してから再度追加してください。

おまけ: 同じブロックをネイティブに作成

ビルド プロセスが整ったら、React でネイティブの WordPress ブロックを作成するのは驚くほど簡単で、php でブロックをテンプレート化するのと大差ありません。 ブロック開発環境のセットアップはこの記事の範囲外ですが、WordPress Block Editor Handbook など、開始するためのリソースが多数あります。 カスタム ブロックを含めることができたら、InnerBlocks を使用してブロックをすばやく構築できます。

これは、React の Call to Action ブロック index.js の例です。 上記で説明したのと同じ戦略が、ここで適用された ACF で表示されます。

 import { __ } from '@wordpress/i18n'; import { registerBlockType } from '@wordpress/blocks'; import { InnerBlocks } from '@wordpress/block-editor'; import { useBlockProps } from '@wordpress/block-editor'; /** * Block Name. * Create an example Call to Action Block * Uses InnerBlocks for editable content within. */ export const blockName = 'call-to-action'; /** * Block Config. * Set basic params for controlling the editor. */ export const BLOCK_CONFIG = { // Set up the block template. CTA_TEMPLATE: [ [ 'core/heading', { placeholder: __('CTA Headline', 'locale'), align: 'center', level: 2, lock: { move: true, remove: true, }, }, ], [ 'core/paragraph', { placeholder: 'Optional CTA text', align: 'center', lock: { move: true, }, }, ], [ 'core/buttons', { lock: { move: true, remove: true, }, className: 'is-content-justification-center', align: 'center', // __experimentalLayout - https://github.com/WordPress/gutenberg/blob/trunk/packages/block-library/src/buttons/block.json layout: { type: 'flex', justifyContent: 'center', }, }, [ [ 'core/button', { text: 'Apply now', lock: { move: true, remove: true, }, }, ], ['core/button', { text: 'Learn more' }], ], ], ], // Set up the allowed blocks. ALLOWED_BLOCKS: ['core/paragraph', 'core/heading', 'core/buttons'], }; // Register the block via WP func. Change 'myplugin' to your plugin or theme. registerBlockType(`myplugin/${blockName}`, { title: __('Call to Action', 'locale'), // Change 'locale' to your locale for internationalization. description: __( 'Call to action block with headline and buttons', 'locale' ), keywords: [__('call'), __('action'), __('cta')], category: 'design', supports: { anchor: true, defaultStylePicker: false, html: false, align: false, }, attributes: { anchor: { type: 'string', default: '', }, }, transforms: {}, variations: [], edit: (props) => { const blockProps = useBlockProps({ className: `wp-block-myplugin-${blockName}`, }); return ( <div {...blockProps}> <div className="cta__inner"> <div className="cta__inner-blocks-wrapper"> <InnerBlocks template={BLOCK_CONFIG.CTA_TEMPLATE} allowedBlocks={BLOCK_CONFIG.ALLOWED_BLOCKS} renderAppender={false} /> </div> </div> </div> ); }, save: () => { return ( <div> <div className="cta__inner"> <InnerBlocks.Content /> </div> </div> ); }, });

行って構築してください!

その他のリソース

  • Bill Erickson の InnerBlocks に関する記事
  • Block Editor に関する Bill Erickson の記事
  • ACF ブロック ガイド
  • ACF レジスタ ブロック タイプのドキュメント
  • WordPress ブロックエディターハンドブック
  • WordPress Block Editor ハンドブック: ブロックの作成のチュートリアル