Vue+Pug:JavaScriptで作成した変数をPugで読込もうとしたが出来ないらしい

Vue+Pug:JavaScriptで作成した変数をPugで読込もうとしたが出来ないらしい

そもそもPUGって何?という方はこちらを参考に。
JSで作成した配列を基にしてPUGでリンクリストを書こうと思い当初、下のようなルートを考えていました。

  1. JavaScriptでリンクの配列を作成
  2. 作成した配列をPUGで読み込む
  3. PUGでeach in ループを回してリンクリストを出力

このルート、どうやら出来ないらしいです。と言う事で、目的の画面を作成するための四苦八苦です。

まずは前提条件から

現在こんなディレクトリ構成でVue.jsのフロントを作成しています。
今回はこの中の太字にした個所についての話です。

Vueプロジェクト/
├── node_modules
├── public/
├── src/
│   ├── assets/
│   ├── components/
│   ├── router/
│   ├── store/
│   └── views/
│       └── Home/
│           ├── Home.js
│           ├── Home.pug
│           ├── Home.scss
│           └── Home.vue
├── App.vue
├── main.js
└── registerServiceWorker.js

例えば『画面サイズを取得してリンクの数をコントロールをしよう』と思い、viewsのHome.jsにこんなコードを書いたとします。※ブラウザの画面サイズを取得、横幅に合わせてリンクの要素数を増減する

let iH = document.documentElement.clientHeight;#ブラウザBODYの高さ
let iW = document.documentElement.clientWidth;#ブラウザBODYの横幅

let b_links = [];
  if (window.matchMedia && window.matchMedia('(max-device-width: 640px)').matches) {
    b_links = [
      {url: 'works', txt: 'WORKS',},
      {url: 'featuer', txt: 'FEATURE',},
      {url: 'skills', txt: 'SKILLS',},
    ];
  }else if(iW <= 1119){
    b_links = [
      {url: 'works', txt: 'WORKS',},
      {url: 'featuer', txt: 'FEATURE',},
      {url: 'skills', txt: 'SKILLS',},
      {url: 'othersites', txt: 'OTHERSITES',},
    ];
  }else{
    b_links = [
      {url: 'works', txt: 'WORKS',},
      {url: 'featuer', txt: 'FEATURE',},
      {url: 'skills', txt: 'SKILLS',},
      {url: 'othersites', txt: 'OTHERSITES',},
      {url: 'about', txt: 'ABOUT',},
      {url: 'contact', txt: 'CONTACT',},
    ];
  }
  return {
    blinks :b_links,
  }

こんな感じで記載すると、スマホの場合(一番上)は要素を3つに、タブレットやスクウェアPCの場合は4要素に、ワイド画面の場合は6要素にと可変するメニューの土台が作成できます。

JSで作った変数をPUGに持っていこうとしたが出来ないことが判明

折角のPugなのだからとHome.pug内で【 each in 】ループを行おうと思っていたのですが、エラー/エラー/エラー。

色々操作してみた結果【JavaScript から PUGへの変数の引き渡し】が課題だとわかり調べてみるとこんな記事が。
pugでJavascriptから引数objectを渡そうとするもエラーでできず

なるほど、そもそも出来ないのか。だとしたらやりたい事を別の方法での実装を考えます。

PUGで出来ないならVueで展開すればよくね?

プログラムの面白いのがこういう「他の方法を考えられる」という点ですよね。
Pugで出来ないならほかの手段を使えば良いのです。
パッと思いつくのはこんな所でしょうか。

  1. JavaScriptでHTMLスクリプトまで作ってしまいDOMで配置する
  2. JavaScriptは配列のみ作成し、Vueで forループを回す
  3. Pug内に分岐用の配列(今回の例だと3タイプ)を用意、JavaScriptで分岐フラグを掃き出し、Vueの If(またはCase)で展開
  4. JavaScriptで分岐用の配列と分岐用フラグを用意、Vueの If(またはCase)で展開
  5. JavaScriptで分岐フラグを掃き出し、Vueの If(またはCase)で配列の要素までゴリゴリ書く

PUGでのループに拘らなければ手段はいくつもあります。

今回は2の方法を採用

まぁね、先に配列作ってるし作り変える手間が減りますからね。

<ul>
  <li v-for="vl in blinks" :key="vl.url">
    <router-link :to="{path:vl.url}" > {{vl.txt}}</router-link>
  </li>
</ul>

Home.vueでこんな形で記載すればリンクを展開してくれます。

チョット解説

■2行目:『 v-for=" ■ in ■s" 』

これがVueの each in です。Laravelで言う所のforeach。
他の言語に慣れていると悩むところは【ループを書く場所】だと思います。
Vueの場合は「繰り返したいタグの場所で記載する」ことになります。
Laravelとかだと<ul>と<li>の間にループ処理書きますが、そうではないので悩んだ末に<ul>に書いてしまう事がないように覚えておきましょう。

■3行目:『 <router-link :to="{path:vl.url}" > 』

今回この処理が一番悩みました。

{{vl.url}}とするとテキストを吐き出すので、ついつい <router-link :to="{{vl.url}}">としてしまいますが、これだとエラーが発生します。

> 1 | 0({{vl.url}})
    |    ^  vue/no-parsing-error

router-linkのto=に変数を渡す場合は次のルールに従い記載していきます。

  1. 文字列変数を入れる場合(※今回の場合)は "{ path : 文字列変数 }" とする
  2. 固定文字列を入れる場合は "{ name : '固定文字列' }" とする
  3. routerに引数登録がある場合はその値を宣言して配置する (例:"{params: {id: task.id, edit_id: 10}}" ※id / edit_id をrouter.js で宣言している場合、その箇所に値を格納する [ path: '/:id/edit/:edit_id', ] )
  4. 変数や定数をカンマで続けた場合、スラッシュで続けた値に変換される

折角なので、先程作成したVueスクリプトをPUGに変換してみる

Home.vueに書いた先程のScriptをPUGで書いてみたいと思います。

ul
  li(v-for='vl in blinks' :key='vl.url')
    router-link(:to='{path:vl.url}') {{vl.txt}}

まぁね、そこまでしてPUGで書く必要があるかって感じになるのは重々承知してますが。
とりあえず、こんな形にすればPUGにJavaScriptの引数を渡すのと同じ結果の実装がPUGを使って可能です。

まとめ

Vue×Pug×JS×SCSSという組み合わせのページ作成をすることがあると思います。
そして、沢山のライブラリが絡めば「どうしても超えられない(出来ない)事」も当然出てきます。
そんな時は別ルートを考えると解決方法が必ずあるのがプログラムの醍醐味。
楽しいですね。

\ 最新情報をチェック /

コメントを残す

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください。