前回はVueRouterを使用して複数のテンプレートを1つのページにまとめるSPAの構築をしました。しかし、実際のポートフォリオサイトには、自己紹介やスキルが書かれているものです。
例えば、スキルであれば箇条書きに表示され、それぞれスキルレベルなどが書かれていることが多いでしょう。このようなデータの形式に沿ってHTMLを記述する場合、繰り返し処理や条件分岐が非常に有効になります。
そこで、第3章では繰り返し処理と条件分岐を使用して自己紹介ページを作ります。Vue.jsを使用しない場合、同じHTMLタグを何度も記述する必要がありましたが、本章の内容が理解できれば、その必要も無くなるでしょう。コーディング時間も大幅に短縮できます。
v-forでデータを表示させる
v-for
ディレクティブは指定した値を繰り返して表示させます。ディレクティブとは指令の意味であり、この属性値を要素に設定することで、様々なビュー側の処理を行うことができます。
それでは実際にv-for
ディレクティブを使用して、自己紹介ページを作りましょう。まず、script.js
を編集します。
// ↓追加
const myinfo = {
"name":"testuser",
"birthday":"1990-03-12",
"place":"Tokyo",
};
let Info = Vue.extend({
template: "#info",
data: function(){
return { "myinfo":myinfo, }; // ←追加
},
});
新たにmyinfo
を定義し、それをInfo
インスタンス内にdata
属性に指定します。続いて、HTMLを編集します。
<template id="info">
<div>
<h2>Information</h2>
<div class="row">
<div class="col-md-6">
<h3 class="text-center">About Me</h3>
<ul>
<li v-for="(value,name) in myinfo">
{{ name }} - {{ value }}
</li>
</ul>
</div>
<div class="col-md-6">
</div>
</div>
</div>
</template>
v-for
ディレクティブを使用し、Info
インスタンスより与えられたmyinfo
をループでひとつずつキーと値を取り出し、表示させています。
注意するべきは、Vue.jsのv-for
ディレクティブ(v-for in
)とJavaScriptのfor in
構文、for of
構文と混同しないようにする点です。下記に違いをまとめます。
JS | 構文 | 効果 |
---|---|---|
Vue.js | v-for="A in B" |
イテラブル要素Bからひとつ取り出して 値を Aと扱う |
JavaScript | for( A of B ){} |
イテラブル要素Bからひとつ取り出して 値を Aと扱う |
JavaScript | for( A in B ){} |
イテラブル要素Bからひとつ取り出して キーを Aと扱う。基本使わない。 |
v-ifで条件分岐させる
v-if
は指定した値が真であれば表示、偽であれば非表示とするディレクティブです。v-for
ディレクティブと並んでよく使われています。
それでは、実際に使ってみましょう。script.jsを下記のように編集します。
// ↓追加
const myskill = {
"HTML":8,
"CSS":6,
"JS":9,
"Vue.js":10,
"Passion":13,
};
let Info = Vue.extend({
template: "#info",
data: function(){
return { "myinfo":myinfo,"myskill":myskill }; // ←修正
},
});
新たにmyskill
を定義し、それをInfo
インスタンスのdata
属性に指定します。後は、HTML側で同様にv-ifとv-forを使用して表示させます。
<template id="info">
<div>
<h2>Information</h2>
<div class="row">
<div class="col-md-6">
<h3 class="text-center">About Me</h3>
<ul>
<li v-for="(value,name) in myinfo">
{{ name }} - {{ value }}
</li>
</ul>
</div>
<div class="col-md-6">
<h3 class="text-center">Skill</h3>
<table class="table table-striped">
<tr v-for="(value,name) in myskill">
<td class="text-center">{{ name }}</td>
<td style="font-size:1.25rem;">
<span v-for="n in value" class="text-primary">★ </span><template v-if="value < 10"><span v-for="n in 10 - value" class="text-secondary">☆ </span></template>
</td>
</tr>
</table>
</div>
</div>
</div>
</template>
myskill
から1つずつ取り出し、その値に当たる数値分だけ★を描画しています。星の数が10に満たない場合、その数だけ☆を描画しています。つまり、HTMLであれば8なので、8個の★の後に2つの☆が描画されます。
注意するべきは、v-ifの場合HTMLの要素ごと表示非表示を行う点にあります。読み込みに時間のかかる要素などをv-ifを使用して何度も表示非表示を繰り返すとブラウザの負担になるので、その場合はv-showディレクティブを使用しましょう。
v-ifとv-forを同時に使うことはできない
公式のドキュメントにも掲載されていることですが、v-forとv-ifを同じ要素に指定することはできません。先程の★を描画するコードを下記のように記述すると、v-for
が優先され、v-if
が発動しません。
//以下はvalueが10を超えるとエラー。
<span v-for="n in value" class="text-primary">★ </span><span v-if="value < 10" v-for="n in 10 - value" class="text-secondary">☆ </span>
もし、v-if
とv-for
を合わせて利用したい場合は、先程のコードの用にtemplate
タグを使用しましょう。template
タグは描画されることは無いので、HTMLの構造を変えてしまうことはありません。
コメント