Vue+Pug:JavaScriptで作成した変数をPugで読込もうとしたが出来ないらしい
Vue+Pug:JavaScriptで作成した変数をPugで読込もうとしたが出来ないらしい
そもそもPUGって何?という方はこちらを参考に。
JSで作成した配列を基にしてPUGでリンクリストを書こうと思い当初、下のようなルートを考えていました。
- JavaScriptでリンクの配列を作成
- 作成した配列をPUGで読み込む
- 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にこんなコードを書いたとします。※ブラウザの画面サイズを取得、横幅に合わせてリンクの要素数を増減する
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
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で出来ないならほかの手段を使えば良いのです。
パッと思いつくのはこんな所でしょうか。
- JavaScriptでHTMLスクリプトまで作ってしまいDOMで配置する
- JavaScriptは配列のみ作成し、Vueで forループを回す
- Pug内に分岐用の配列(今回の例だと3タイプ)を用意、JavaScriptで分岐フラグを掃き出し、Vueの If(またはCase)で展開
- JavaScriptで分岐用の配列と分岐用フラグを用意、Vueの If(またはCase)で展開
- JavaScriptで分岐フラグを掃き出し、Vueの If(またはCase)で配列の要素までゴリゴリ書く
PUGでのループに拘らなければ手段はいくつもあります。
今回は2の方法を採用
まぁね、先に配列作ってるし作り変える手間が減りますからね。
1 2 3 4 5 |
<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 2 |
> 1 | 0({{vl.url}}) | ^ vue/no-parsing-error |
router-linkのto=に変数を渡す場合は次のルールに従い記載していきます。
- 文字列変数を入れる場合(※今回の場合)は “{ path : 文字列変数 }” とする
- 固定文字列を入れる場合は “{ name : ‘固定文字列’ }” とする
- routerに引数登録がある場合はその値を宣言して配置する (例:”{params: {id: task.id, edit_id: 10}}” ※id / edit_id をrouter.js で宣言している場合、その箇所に値を格納する [ path: ‘/:id/edit/:edit_id’, ] )
- 変数や定数をカンマで続けた場合、スラッシュで続けた値に変換される
折角なので、先程作成したVueスクリプトをPUGに変換してみる
Home.vueに書いた先程のScriptをPUGで書いてみたいと思います。
1 2 3 |
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という組み合わせのページ作成をすることがあると思います。
そして、沢山のライブラリが絡めば「どうしても超えられない(出来ない)事」も当然出てきます。
そんな時は別ルートを考えると解決方法が必ずあるのがプログラムの醍醐味。
楽しいですね。
-
前の記事
Vue.js:Vueで作成したページは漏れなくSPA?ちょっとした疑問解決 2021.03.25
-
次の記事
Django:QuerySetのJSON変換で大ハマリした件 2021.03.30
コメントを残す