Vue.jsで実装しているブロックエディタの汎用化に向けた考察(5)

公開

PowerCMS Xのカスタム編集タイプでコンポーネントをベースにしたブロックエディタ(設計済のHTML/CSSコンポーネントに対応した入力フィールドを用意するブロックエディタ)を実装する個人プロジェクトです。これまでの記事はタグ「ComponentBlocks」一覧」でご覧いただけます。

Vue.jsの知識をもっと深めた方が良いのか?などとモヤモヤし2022年10月以来手が止まっていたのですが、ここ数日でコードを再度眺め整理することができ、CMSで管理・出力したい(ないし手書きしてもらいたい)内容とエディタのコアとなるコードが明確になりました。(知識は深めたい…)

  • ブロックの上下・削除ボタンをクリックした際にemitsでひたすら親コンポーネントにバケツリレーしていたのですが、BlockControllerコンポーネント自身で完結できるようになりました
  • マルチブロックコンポーネントは利用者が直接編集する必要がないので、ブロックの定義を記述していく代替テンプレートからJSファイルに出しました

ユーザーが入力するブロックの定義は以前にも掲載しましたが下記のような感じです。

const LayoutImage = Vue.defineComponent({
  props: ['element', 'index'],

  data() {
    return {
      store,
    }
  },

  template: `
    <div class="row">
      <div class="col-4">
        <assetselector :element="element" :index="index" />
      </div>
      <div class="col-8">
        <editor
          <mt:if name="component_blocks_tinymce_api_key">api-key="<mt:var name="component_blocks_tinymce_api_key" escape />"</mt:if>
          :init="store.initTextEditor"
          v-model="element.text"
          class="form-control inline-mce text"
        />
      </div>
    </div>
  `,
});

テキストエリアでTinyMCEを使う設定を入れているのでdataが入ってきますが、見出しテキストと見出しレベルの選択を入力するぐらいならばもっと簡単です。Bootstrapのクラス名等を外したコードを示します。

const Heading = Vue.defineComponent({
  props: ['element'],

  template: `
    <input type="text" v-model="element.text">
    <div>
      <label>
        <input type="radio" v-model.number="element.level" :value="2">
        見出し2
      </label>
      <label>
        <input type="radio" v-model.number="element.level" :value="3">
        見出し3
      </label>
      <label>
        <input type="radio" v-model.number="element.level" :value="4">
        見出し4
      </label>
    </div>
  `,
});

課題は上記ブロックの定義の他にブロックを追加した時にリアクティブなデータオブジェクトに追加するオブジェクトの定義をどう追加してもらうか。ブロックの編集画面が実現すれば、PHPで解決できるかもしれません。

// ブロック毎の保存データを定義
window.compoenentBlocksSettings.setBlockData = (app, blockData, type) => {
  switch (type) {
    case 'heading':
      blockData['text'] = '';
      blockData['level'] = 2;
      break;
    case 'text':
      blockData['text'] = '';
      break;
    case 'image':
      blockData['asset_id'] = 0;
      break;
    case 'layout_image':
      blockData['asset_id'] = 0;
      blockData['text'] = '';
      break;

画面キャプチャ:開発中のブロック定義編集画面
v-model.numberの記述を忘れていましたので修正しました。テキストと数値を個別に指定できるようにしました。

それにしても、エディタのコアなコードは100行ぐらいで後はひたすらブロックのコンポーネント定義をしているだけというのがすごいなと思っています。リアクティブなデータオブジェクトを操作するだけで編集画面に反映されるのが個人的には楽しいです。メンテナンスが楽そうですがユーザーにもVue.jsの知識が求められるのが難点でしょうか。PowerCMS 6の「フィールドブロックビルダー」はノーコード・ローコードな感じですよね。