Vue.jsを利用したクイズアプリ
ルーティングとは
ルーティング(Routing) とはVue.jsにおいて, リクエストされたURLに応じて,コンポーネントを選択して表示する仕組みのことです. シングルページアプリケーション(Single Page Application: SPA) と呼ばれる 単一のWebページで動的にコンテンツを切り替える設計方法を実現するために用いられます. Webページの遷移が発生しないため,サーバとの通信を減らし高速なコンテンツの遷移が可能になることに加え, ネイティブアプリ(JavaやSwiftで開発されたアプリ)の代替としても採用されます. 今回はこのルーティングを利用してクイズアプリを実装してみましょう.
クイズアプリ
それでは, クイズアプリ を実装して行きましょう. 下記が完成したソースコードです. 「問題」をクリックするとクイズの問題が表示され, 「解答」をクリックすると対応するクイズの解答が表示されます.
See the Pen クイズアプリ by Naoto Mukai (@nmukai) on CodePen.
CDNのリンク
ルーティングを実装するには,vue.js に加え, vue-route.js を導入する必要があります. CodePenのSettingsで下記のようにCDNを追加してください.
ルータの作成
それではルーティングの役割を担う VueRouter クラスのインスタンスをを作成しましょう.
このルータには,2つのコンポーネント(component
)を登録します.
コンポーネントの実体は,変数のQuizBlock
とAnsBlock
で宣言しています.
それぞれのコンポーネントには,path
とname
のプロパティを設定します.
path
はリクエストされるURL,name
はルートの名前を表します.
また,Vue クラスに router
をプロパティとして登録しておきます.
var QuizBlock = {
template: "<div> question </div>"
}
var AnsBlock = {
template: "<div> answer </div>"
}
var router = new VueRouter({
routes: [
{
path: "/quiz",
name: "quiz",
component: QuizBlock
},
{
path: "/answer",
name: "answer",
component: AnsBlock
}
]
})
new Vue({
el: "#main",
router
})
ルーティングを利用するにはrouter-link
タグを利用します.
to
属性は表示したいコンポーネントのpath
を指定します.
router-link
タグは,リンクを表すa
タグとして表示されます.
また,router-view
タグは,コンポーネントを表示する領域です.
<div id="main">
<p>クイズ</p>
<router-link to="/quiz" >問題</router-link>
<router-link to="/answer" >解答</router-link>
<router-view />
</div>
ここまで実装すると,下記のようになります.
問題をクリックするとrouter-view
タグに,QuizBlock
のコンポーネントが表示されます.
同様に解答をクリックするとrouter-view
タグに,AnsBlock
のコンポーネントが表示されます.
ルートパラメータ
router-link
タグで表示するコンポーネントにデータを渡すには ルートパラメータ という方法を用います.
この方法では,path
属性にパラメータ(キーと値のペア)が埋め込まれ,表示されるコンポーネントでデータを受け取ることができます.
まず,ルータのpath
プロパティに,パラメータのキーを記述します.
例えば,quiz
という名前のキーであれば,:quiz
を最後に追加します.
次にrouter-link
タグのto
属性を修正します.
v-bind
ディレクティブを利用して,to
属性にはオブジェクトを指定します.
このオブジェクトには,name
とparams
を指定します.
name
はルートの名前,params
はコンポーネントに渡すパラメータ(キーと値のペア)を指定します.
コンポーネントでは,ルートパラメータで取得したデータを
$route.params.[パラメータのキー]
で参照できます.
ここでは,$route.params.quiz
を参照し,“question"と"answer"の文字列を表示しています.
var QuizBlock = {
template: "<div> {{ $route.params.quiz }} </div>"
}
var AnsBlock = {
template: "<div> {{ $route.params.quiz }} </div>"
}
var router = new VueRouter({
routes: [
{
path: "/quiz/:quiz",
name: "quiz",
component: QuizBlock
},
{
path: "/answer/:quiz",
name: "answer",
component: AnsBlock
}
]
})
<div id="main">
<p>クイズ</p>
<router-link v-bind:to="{name: 'quiz', params: {'quiz': 'question'}}" >問題</router-link>
<router-link v-bind:to="{name: 'answer', params: {'quiz': 'answer'}}" >解答</router-link>
<router-view />
</div>
クイズの作成
最後にクイズの問題と解答を作成しましょう.
Vueクラスのdata
プロパティでquizzes
に問題と解答のデータを保持させます.
new Vue({
el: "#main",
router,
data: {
quizzes: [
{
question: "Q. ぼうしの中に入っている動物はなに?",
answer: "A. うし"
},
{
question: "Q. 飲むとおこられるジュースってなに?",
answer: "A. コーラ"
}
]
}
})
v-for
ディレクティブを利用して,quizzes
の要素数だけ繰り返して,問題と解答のリンクを表示します.
このとき,Mustache構文を利用して,問題番号を表示しています.
また,ルートパラメータのパラメータとして,文字列ではなくオブジェクト(quizzes
の要素)を指定していることに注意してください.
<div id="main">
<p>クイズ</p>
<template v-for="(quiz, i) in quizzes">
<p>
<router-link v-bind:to="{name: 'quiz', params: {'quiz': quiz}}" >問題{{ i }}</router-link>
<router-link v-bind:to="{name: 'answer', params: {'quiz': quiz}}" >解答{{ i }}</router-link>
</p>
</template>
<router-view />
</div>
ルートパラメータはオブジェクトであり,question
とanswer
を参照することができます.
問題や解答のリンクをクリックすると対応する文字列が表示されれば完成です.
var QuizBlock = {
template: "<div> {{ $route.params.quiz.question }} </div>"
}
var AnsBlock = {
template: "<div> {{ $route.params.quiz.answer }} </div>"
}