Ownedmedia ウェブ制作に役立つコンテンツを発信中!

Pug 2020.11.20

Pugでeach inを使って多重階層の入れ子リストを作成する

Tags: ,,,

JavaScriptのテンプレートエンジンである「Pug」では、HTMLの拡張メタ言語のように効率よくマークアップが出来ると共に、繰り返し処理や条件分岐、ファイルのインクルードなどができます。当サイトでも過去にいくつか記事をアップしておりました。

 

今回はPugにある配列処理ができる「each in」を使って、目次などで見かける多重階層の入れ子リストを簡単に作成してみたいと思います。入れ子になっているリストですが、普通にマークアップするとかなり面倒ですし、項目の数が多くなって且つ階層も深くなるとカオスな感じになってきます。そこでPugを使うことで、項目の内容は連想配列に、HTMLは繰り返し処理で動的に生成されるようにしていきます。

 

配列を展開して値ごとに処理ができる「each in」

Pugに備えられている「each in」を使うと配列を展開し、その値ごとに処理を行うことができます。使い方の例として値をそのまま文字列として出力する場合には下記のように記述します。

each 値 in 配列
  #{値}

 

値には繰り返し処理の中で使われる変数が入ります、そしてinの後に対象となる配列が続きます。繰り返し処理はeach in文の後に改行とインデントを入れて続けていきます。変数の値を出力する場合には、#と波括弧で変数を囲むことで出力することができます。

 

リスト項目の内容を連想配列で格納し、each inで展開・出力していく

それでは実際に入れ子のリストをPugを使って作成していきます。まずはリストの内容を下記のようにオブジェクトとして変数内に入れておくようにしておきます。今回は変数として保持していますが、内容が多くなる場合には、別途個別のPugファイルあるいはJSONファイルとして切り分けておくといいですね。その方法については過去記事「Pugでテンプレートとデータでファイルを切り分けた開発を行う」で詳しくまとめていますのでご参考に。

【Pug】

// data
-
  var items = [
    {
      text: 'リスト項目1',
      anchor: '#anchor_1',
      childItems: [
        {
          text: 'リスト項目1-1',
          anchor: '#anchor_1_1'
        },
        {
          text: 'リスト項目1-2',
          anchor: '#anchor_1_2'
        },
        {
          text: 'リスト項目1-3',
          anchor: '#anchor_1_3',
          grandChildItems: [
            {
              text: 'リスト項目1-3-1',
              anchor: '#anchor_1_3_1'
            },
            {
              text: 'リスト項目1-3-2',
              anchor: '#anchor_1_3_2'
            }
          ]
        },
      ]
    },
    {
      text: 'リスト項目2',
      anchor: '#anchor_2'
    },
    ........
  ];

 

Pugで変数が複数になる場合には、改行とインデントを入れてからを定義することで、ハイフンをなんども書かなくて済みます。また、上記のように入れ子のリスト項目は、親のリスト項目のオブジェクトの値に配列として入れていくという形になります。各リスト項目のオブジェクトには出力したいデータをそれぞれ入れておきます。

 

続いてこのデータを展開するテンプレートを作成していきます。今回はol要素とli要素をベースに、リスト項目にアンカーリンクを設定する想定で進めています。each inの後に続けてli要素でリスト項目を出力していきますが、子要素となるリストの情報があるかどうかを条件分岐にかけます。項目がある場合には子要素のリストを出力し、なければそのままリスト項目の内容を出力するという感じです。あとは入れ子の階層数だけ同じように繰り返していきます。

【Pug】

// template
ol
  each item in items
    li
      if item.childItems
        a(href=item.anchor) #{item.text}
        ol
          each childItem in item.childItems
          li
            if childItem.grandChildItems
              a(href=childItem.anchor) #{childItem.text}
              ol
                each grandChildItem in childItem.grandChildItems
                  li
                    a(href=grandChildItem.anchor) #{grandChildItem.text}
            else
              a(href=childItem.anchor) #{childItem.text}
      else
        a(href=item.anchor) #{item.text}

 

上記では3階層の例になりますが、あまり階層が深くなりすぎる場合にはコードの見通しが悪くなるので、個別に外部ファイルとして切り分けてインクルードさせるなどの方法が必要になるかもしれませんね。

 

実際に作成したサンプルはこちらで確認ができます。ブログコンテンツの目次になどでよく見かける形になっていますね。

See the Pen
nested-list_by_pug
by designsupply (@designsupply)
on CodePen.

 

先ほどのPugで書いたテンプレートはHTMLとして出力されるとこのような形になります。綺麗に入れ子になっているのが確認できますね。

【HTML】※一部抜粋

<ol>
  <li>
    リスト項目1
    <ol>
      <li>リスト項目1-1</li>
      <li>リスト項目1-2</li>
      <li>
        リスト項目1-3
        <ol>
          <li>リスト項目1-3-1</li>
          <li>リスト項目1-3-1</li>
        </ol>
      </li>
    </ol>
  </li>
  <li>リスト項目2</li>
</ol>

 


 

今回はPugを使って多重階層の入れ子リストをマークアップする方法についてまとめてみました。大量のリスト項目や複雑な階層構造になっている場合に、そのままマークアップする形では手間がかかったりミスが起こりやすいのですが、データとテンプレートに切り分けた上で、繰り返し処理で動的に出力ができるようになることで、簡単且つ正確にマークアップができるようになりますので、ぜひ試してみてくださいね。

この記事を書いた人

オガワ シンヤ

DesignSupply.代表 / ディレクター・ウェブデザイナー・フロントエンドエンジニアをやっています。「ウェブとデザインでヒト・モノ・サービスを繋げ新しい価値を生み出す」をコンセプトに日々奮闘中!制作中はチョコレートが欠かせない三十路Webクリエイター。

  • Twitter

コメントフォーム

記事に関するご質問やご意見などありましたら下記のコメントフォームよりお気軽に投稿ください。なおメールアドレスは公開されませんのでご安心ください。

内容に問題なければ、お名前・ハンドルネームとメールアドレスを入力いただき、下記の「コメントを送信」ボタンを押してください。

CAPTCHA


この記事もよく読まれています

Scroll to Top
ご質問・ご相談はありませんか ?