Gutenberg(ブロックエディタ)メモ -ハンドブックでわからないところ1

WordPressのGutenberg
WordPressのGutenberg

全く進まないので、WordPressのGutenberg Handbookを頭からみています。が、サンプルがまずわからない…。

そのため何となく理解したことをメモ的に残します。残さないと確実に忘れるので。

語句や説明や認識に間違いがある可能性もあるので、間違いがあればごめんなさい。

最初に

Reactを学べば解決する疑問は多いと思うので、最初から(か同時か後からでも)Reactの基本的な部分を学ぶことをお勧めします。

参考サイト

肝心のハンドブックは以下のものです。

以下のサイトで日本語訳と少し解説が載っていて非常に助かります。

ただし、どうもハンドブックが更新されたのか内容があいません。恐らくこのページの内容にそっているのかなと思いますが、その点はあまり調べられていません。

なお、constreturnの後にHTMLタグ(実際にはHTMLタグではありませんが)が書かれているコードは、基本的にES5にトランスパイルする必要がある(最新ブラウザでしか動かさない場合は別だと思いますが)ので、トランスパイルやその必要性がわからない方はまずそのあたりを調べてからでないと無理かと思います。

JSコードのところにESNextと書いていますが、本来はES◯とかJSX記法とかREACTとか書かねばならないのかもしれませんが、スペースもなく区分の理解が微妙なのでESNextと記載しています。

全体がわかるサンプルコード

以下はsaveまで載っている貴重なサンプルです。

ハンドブックではsaveを含めて全体のサンプルがほとんど載っていませんので、教科書的な形がわかることは稀です。

また、ハンドブックではほとんど説明されていないことも散見され、GitHubにあるGutenbergのページやGutenbergプラグインのコード、解説記事などを必要応じて探して読む必要があります。

PHP側の構造


add_action( 'enqueue_block_editor_assets', function() {
  wp_enqueue_script(
    'myplugin-gutenberge',
    plugins_url( 'block.js', __FILE__ ),
    [ 'wp-blocks', 'wp-element' ]
  );
} );

自分でカスタムするファイルをプラグインの形にして作成する場合、上記のような記述を行って必要なJSファイルを読み込ませる必要があります。

Gutenbergがコアに入った際に起こった問題


Uncaught TypeError: Cannot read property 'RichText' of undefined

api-fetch.min.js?ver=5.0-beta3-43865:1
Uncaught (in promise) TypeError: Cannot read property 'hasQueryArg' of undefined

WordPress5.0以降はGutenberugがコアに入ることになりますが、それを先行してためせるbeta版(今回はbeta3)に切り替えた際に上記のようなエラーがでました。

これは、前項のenqueue_block_editor_assetswp_enqueue_scriptないに記述が足りないために起こった模様です。
そのため以下のように必要な項目を追加する必要があります。


add_action( 'enqueue_block_editor_assets', function() {
  //JS側でwp.editorやwp.componentsを使う場合を想定
  wp_enqueue_script(
    'myplugin-gutenberge',
    plugins_url( 'block.js', __FILE__ ),
    [ 'wp-blocks', 'wp-element', 'wp-components', 'wp-editor' ]
  );
} );

プラグインではなくても動作していたようですが、コアにはいると必要な情報をちゃんと配列内に記述しなければエラーになってしまい、場合によっては以下のようなエラーが出て投稿画面が使えなくなります。

This block has encountered an error and cannot be previewed.

JS側の構造


const { registerBlockType } = wp.blocks;

registerBlockType('my-plugin/event-location', {
  title: 'meta author',
  category: 'widgets',

  attributes: {
    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" />;
  },

  save () {
    return null
  }
})

上記は「Gutenbergメモ metaデータを設定する」の記事で実際に試作したmeta用のコード(JSのみですが)ですが、これを以下の説明に用います。

APIからの読み込み


const { registerBlockType } = wp.blocks;

まず最初のconstですが、これでGutenbergプラグイン内にあるAPIにアクセスして、個別に機能を使えるように設定しています。

上記のコードでは基本となるregisterBlockTypeですが、以下のようにwp.ではじまるものは全て同じ役割となります。


const { Fragment } = wp.element;
const {
    RichText,
    BlockControls,
    AlignmentToolbar,
    InspectorControls,
} = wp.editor;

例えば、以下のようにedit内にFragmentを記載しただけで作ったとします。


const { registerBlockType } = wp.blocks;
//エラーを見るために以下をコメントアウト
//const { Fragment } = wp.element;

registerBlockType( 'my-gutenberg-/test', {
    title: 'test',
    icon: 'universal-access-alt',
    category: 'layout',

  edit () {
    return (
      <Fragment>
        <p>test</p>
      </Fragment>
    );
  },
  save () {
    return null
  }
} );

上記のコードを実行する(管理画面で実際にこのブロックを追加する)と以下のようなエラーが開発者ツールで見られるはずです。

ReferenceError: Fragment is not defined

こういうエラーの場合は、Gutenberg APIから必要な機能を使う指定が記述されていないという可能性が高いと思われます。

@wordpress

ハンドブックにもありますが、GitHubでも以下のような記述を目にするはずです。


import { RadioControl } from '@wordpress/components';

これはローカルに開発環境を作った際に、Gutenberg専用の開発コンポーネントを入れた状況で使う記述です。

サーバー内のWordPressにGutenbergプラグインがあれば(WP5.0以降はコアにあるので不要)、上記を以下のように書き換えてサーバーにアップすれば同様にコンポーネントの読み込みが可能です。


const { RadioControl } = wp.components;

importfromをなしにしてconstに書換え、@wordpresswp.に書き換える感じです。

Fragment

wp.elementで設定して使えるFragmentですが、以下のページのなかほどに説明があったので引用します。

The <Fragment> component is very useful when you need to return multiple top-level elements from the edit or save functions but don’t want to wrap them in an element that will be outputted.

<Fragment> won’t output any markup at all on the front end and acts like an invisible container. It’s just a convenient way to return multiple top-level elements and is an alternative to the previous method of returning an array of elements instead.

簡単に言えば、editsave内のreturn部分ではトップレベルのラッパー要素が必要ですが、実際に投稿画面内(edit時)やページに出力時(save時)にはそのラッパー要素を出したくない場合あり、そういう場合に用いられます。

具体的な動作としては、内部ではトップレベルのラッパー要素として機能しつつ、出力時には出力されない便利な要素、という感じです。

ちゃんと出力したい場合にはFragmentではなくdivなどを使う必要があります。

save/edit内の変数の値

attributesで記載した名称を用いる変数は、saveedit内において書き方により以下のような違いがあります。


registerBlockType( 'my-plugin/test-inspector', {
  title: 'test-inspector',
  icon: 'universal-access-alt',
  category: 'layout',

  attributes: {
    alignment: {
      type: 'string', //文字列を指定 「center」という文字列を設定すると仮定
    },
    check:{
      type:'boolean', //真偽値を指定 trueを設定すると仮定
    },
    content: {
      type: 'array', //配列を指定 「入力内容」という文字列を設定すると仮定
      source: 'children',
      selector: 'p',
    }
  },
  edit({ attributes }) {
    console.log(attributes.alignment); //center
    console.log({alignment}); //{alignment: "center"}
    console.log(attributes.check); //true
    console.log({check}); //{check: true}
    console.log(attributes.content); //["入力内容"]
    console.log({content}); //{content: Array(1)}
  },
}

attributesの対象となる値を取り出したい場合は、ES5でもESNextでもattributes.alignmentのように記載する必要があります。

attributesの値をeditやsave内に反映する際の書き方


//attributesでcontentという名称で設定した場合
edit: (props) {
    var content = props.attributes.content;
},

attributesの値をeditsave内に反映するためには上記のようにpropsを使う書き方もありますが、attributesの方を使う以下のような書き方でも良い模様です。


//attributesでcontentという名称で設定した場合
edit:( {attributes} ) {
  const { content } = attributes;
},

結び

公式の用意するコーデックスやハンドブックが必ずしも網羅的であるわけではないと理解はしていますが、それにしても実例サンプルが少な過ぎるように思いました。

WordPressはコーデックスが充実しているので、そのイメージが強いから不満に思うのかもしれませんが。

もっともその辺りを問題としないレベルの方が対象だという意思表示ともとれるので、そういう意味では今後もこのまま変わらないのでしょう。

関連記事

Gutenberg(ブロックエディタ)に関連する記事一覧。

1人がこの記事を評価

役に立ったよという方は上の「記事を評価する」ボタンをクリックしてもらえると嬉しいです。

連投防止のためにCookie使用。SNSへの投稿など他サービスとの連動は一切ありません。

コメント欄