ME to FE

デザインからフロントエンドのことまでごちゃまぜで綴ります

(Pug)繰り返すのはイヤだ!!! listで使えるmixinコード

f:id:saimari02:20190515214913p:plain
繰り返すのはイヤだ!!! listで使えるmixinコード(Pug)

Pugを使いこなしたい!

「もっとPugを使いこなしたい!」
と思っている方いませんか??

私は業務ではPugを使ってマークアップをしています。
最初のうちは変数を使ったりするだけで、ほとんどPugを使いこなせていませんでした。
そんな私でも導入できたmixinのコードを紹介します。

内容

リスト形式のニュース一覧を例に、 <ul><ol>のリストで役に立ちそうな書き方をmixinを使って実装してみます。

記述例(Pug)

ul.news__list
    mixin news-list(...newsLists)
        each news, index in newsLists
            li.news__item
                a.news__link-post(href=news.linkHref,target=news.linkTarget,rel=news.linkTarget === '_blank' ? 'noopener noreferrer' : '')
                    .news__number #{index + 1}
                    .news__category= news.category
                    .news__date= news.date
                    .news__title= news.title
                        if news.iconNew == true
                            span.icon--new NEW
    +news-list(
        {
            linkHref: '/news-20190521/',
            linkTarget: '_blank',
            category: 'カテゴリー名',
            date: '2019.05.21',
            title: 'タイトル2',
            iconNew: true,
        }, {
            linkHref: '/news-20190520/',
            category: 'カテゴリー名',
            date: '2019.05.20',
            title: 'タイトル1',
            iconNew: false,
        }
    )

コンパイル後(html)

<ul class="news__list">
    <li class="news__item">
        <a class="news__link-post" href="/news-20190521/" target="_blank" rel="noopener noreferrer">
            <div class="news__number">1</div>
            <div class="news__category">カテゴリー名</div>
            <div class="news__date">2019.05.21</div>
            <div class="news__title">タイトル2<span class="icon--new">NEW</span></div>
        </a>
    </li>
    <li class="news__item">
        <a class="news__link-post" href="/news-20190520/" rel="">
            <div class="news__number">2</div>
            <div class="news__category">カテゴリー名</div>
            <div class="news__date">2019.05.20</div>
            <div class="news__title">タイトル1</div>
        </a>
    </li>
</ul>

パーツごとに解説

1. 定義

mixin news-list(...newsLists)

まずnews-listという名前で、mixinを定義します。(この例ではli全体を対象としています)
Rest引数を利用し、...newsListsの配列全てを受け取ります。

参考: 分割代入や引数の「残り全部」を持ってくるやつ……。(現代的JavaScriptおれおれアドベントカレンダー2017 – 17日目) | Ginpen.com

2. 繰り返しの指定

each news, index in newsLists

each in文を使います。
newsnewsListsの値を、
indexnewsListsのインデックス番号が格納されています。

3. 要素の中に引数を指定

li.news__item
    a.news__link-post(href=news.linkHref,target=news.linkTarget,rel=news.linkTarget === '_blank' ? 'noopener noreferrer' : '')
        .news__number #{index + 1}
        .news__category= news.category
        .news__date= news.date
        .news__title= news.title
            if news.iconNew == true
                span.icon--new NEW

この例では、引数のnewsListsをオブジェクトで返すため、変数名.プロパティ名でそれぞれ記述していきます。
以下の通りです。

  • news.linkHref
  • news.linkTarget
  • news.category
  • news.date
  • news.title

※オブジェクトの内容は追って説明します。


a.news__link-post(href=news.linkHref,target=news.linkTarget,rel=news.linkTarget === '_blank' ? 'noopener noreferrer' : '')

rel属性の値を、三項演算子で出し分けしています。
traget属性に_blank(別窓ウィンドウでリンクを開く)の値が入っているときは、rel属性にnoopener noreferrerを代入します。

rel="noopener noreferrer"については、以下を参考にして下さい。ここでは省略します。

参考: リンクを作る時の target="_blank" の危険性 - 隙あらば寝る


.news__number #{index + 1}

#{index + 1}で配列のインデックス番号を取得していますが、プログラミング言語のインデックス番号は0から始まるため、+1をして強制的に1から始まるようにしました。

ここで悩ましいのは#{index++}とインクリメント演算子で記述すればよくない?
と思いましたが、、結果、どうやらできないらしい・・・!!
あくまで配列のインデックス番号を取得するのみということなのか・・・。
うまく説明できないので、お分かりの方お力添えをお願いします!


.news__title= news.title
    if news.iconNew == true
        span.icon--new NEW

if文を使って、NEWの表示を出すか出さないかの判定をしています。
trueであればspan.icon--new NEWが出力されます。

※ここではtrue以外の値を指定すれば出力されませんが、有無がわかるようにtruefalseのどちらかを指定します。

4. 出力結果の指定

+news-list(
    {
        linkHref: '/news-20190521/',
        linkTarget: '_blank',
        category: 'カテゴリー名',
        date: '2019.05.21',
        title: 'タイトル2',
        iconNew: true,
    }, {
    ~~ 省略 ~~
    },
)

mixinで定義したnews-listを呼び出します。
呼び出し方法は、+とmixin名を指定します。
オブジェクトのプロパティ名と内容は、以下の通りです。

プロパティ名 内容
linkHref リンクパスの記述
linkTarget 別窓リンクの場合_blankを記述
category カテゴリー名の記述
date 日付の記述
title タイトルの記述
iconNew NEWの表記が必要な場合trueを、不必要であればfalseを記述

補足

この例では、mixinの定義と呼び出しを1ファイル内で行いましたが、mixinの要素だけ別ファイル化し、includeして使うことも可能です。

  • mixinの数が増えてきたら、mixinだけをまとめた別ファイルで管理する。
  • コンポーネントとしてmixinを使用する場合は、コンポーネントごとに別ファイルで管理する。

まとめ

同じ記述を何度も繰り返すのイヤですよね??
それに、同じ記述を手作業で増やすことで、思わぬミスが発生することもあります。
変更箇所を必要最低限に抑えることで、作業の手間とミスを減らすことが可能です!
なんてHAPPYなんだ〜!

今回紹介した記述例の中には、mixin以外にもPugのちょっとした小技を盛り込んだので是非他のところでも応用してみて下さい。

Pug公式ドキュメント