Vue.jsで資格の過去問題解説アプリを作成したいと考えています。
リストの問題がクリックされたとき、個別の詳細ページに遷移させたいです。
###DynamoDBの設定
検索に解説本文を含めてしまうとDynamoDBで多くのリソースを消費してしまうため、リスト&検索用(questionListData)と詳細用(questionDetailData)の2つのテーブルを作成しています。それぞれのデータ形式は下記の通りです。
(questionListData)
JSON
1{ 2 "q_year" : "2012", 3 "q_no" : "1", 4 "category" : "english", 5 "q_title" : "QUESTION_TITLE", 6 "q_id" : "2012q001" 7 }, 8 { 9 "q_year" : "2012", 10 "q_no" : "2", 11 "category" : "english", 12 "q_title" : "QUESTION_TITLE", 13 "q_id" : "2012q002", 14 },
(questionDetailData)
JSON
1{ 2 "q_id" : "2012q001", 3 "q_body" : "QUESTION_BODY", 4 "q_desc" : "QUESTION_DESCRIPTON", 5 "image_url" : "", 6 "image_alt" : "" 7 }, 8 { 9 "q_id" : "2012q002", 10 "q_body" : "QUESTION_BODY", 11 "q_desc" : "QUESTION_DESCRIPTION", 12 "image_url" : "", 13 "image_alt" : "" 14 },
上記のデータをBoto3を使って、それぞれのDynamoDBのテーブルに格納しています。Serverlessフレームワークのofflineプラグインを使って、ローカル環境でAPI Gatewayを実行しています。Postmanでそれぞれのエンドポイントから適切にデータが取得できることを確認しています。
実現したいのは、**リストのq_idを詳細用の「http://localhost:3000/question/{q_id}」に当てはめて、リストページからそれぞれの個別ページに遷移させること**です。
###Vuejsの設定
現在のVueの構造と希望の形を簡単なイメージにしてみました。
まずリスト用データはRootInstance(main.js)でAxiosを使って読み込んでいます。これをdataでquestionsとしてOverview、QuestionListと下層に流しています。
javascript
1import Vue from 'vue' 2import VueRouter from 'vue-router'; 3import Axios from 'axios'; 4 5Vue.use(VueRouter); 6Vue.use(Axios); 7 8import routes from './util/routes'; 9const router = new VueRouter({routes}); 10 11new Vue({ 12 el: '#app', 13 data: { 14 questions: [] 15 }, 16 created() { 17 Axios.get('http://localhost:3000/questions/2012').then(response => { 18 this.questions = response.data 19 }); 20 }, 21 router 22});
QuestionList.vueでは下記のようにして、2012年度分のデータを表示することができました。一応<router-link>で囲っていますが、当然詳細ページに遷移することはできません。
javascript
1<template> 2 <div class="list"> 3 <h1>QuestionList page.</h1> 4 <div v-for="question in questions" v-bind:question="question.question"> 5 <router-link> 6 <h2>{{ question.q_title }}</h2> 7 </router-link> 8 </div> 9 </div> 10</template> 11 12<script> 13 export default { 14 name: 'QuestionList', 15 props: ['questions'] 16 } 17</script>
Axiosの公式ドキュメントなどから、paramsにq_idを指定して下記のような形になるのかなーと想像しますが、まだ具体的な解決ができずにいます。
axios.get('http://localhost:3000/question/', { params: { id: question.q_id } })
リストデータを読み込む階層など、改善の余地は多々あるかと思いますが、「リストページからq_idを頼りに詳細ページへ遷移する方法」を教えて頂ければなと思います。
有用そうなソースも歓迎です。
###[2017/08/19追記 ページ遷移できました]
aro10さんの指摘に沿って次のように修正し、ページを遷移させることができました。
Vue-RouterのPath設定に誤りがありました。
(修正前) { path: '/question/:id', component: QuestionDetail, name: 'detail'}
(修正後) { path: '/question/:q_id', component: QuestionDetail, name: 'detail'}
上記のようなルート定義を作成したうえで、QuestionList.vueのrouter-link部分を下記のように修正したところ、無事ページ遷移させることができました。
javascript
1<template> 2 <div class="list"> 3 <h1>QuestionList page.</h1> 4 <div v-for="question in questions" v-bind:question="question.question"> 5 <router-link :to="{ name: 'detail', params: {q_id: question.q_id}}"> 6 <h2>{{ question.q_title }}</h2> 7 </router-link> 8 </div> 9 </div> 10</template> 11 12<script> 13 export default { 14 name: 'QuestionList', 15 props: ['questions'] 16 } 17</script>
###ページ遷移と同時に詳細用API(/question/{q_id})を発火したい
アドバイスによりページ遷移が完了しましたが、現状では詳細情報を取得するためのAPI(http://localhost:3000/question/{q_id})が未発火なので、遷移先のページが空白のままです。
RootInstanceのcreated()で2012年の問題群を取得したように、ページ遷移したと同時にq_idを上記APIの{q_id}に代入して個別問題を取得したいと考えているのですが、どのような方法が考えられるでしょうか。動作こそしないものの、現在のDetailのコードなども早めに追記しようと思います。
※動作しないので参考にしないでください。
とりあえず詳細データのq_bodyを表示させたいと考えています。現状は詳細情報が取得されておらず、questionが空の状態なので、<div v-else>が実行されて、ページに「No Page.」と表示だけされています。
javascript
1<template> 2 <div class="detail"> 3 <div v-if="question != null"> 4 <h2>{{ this.question.q_body }}</h2> 5 </div> 6 7 <div v-else> 8 <p>No Page.</p> 9 </div> 10 </div> 11</template> 12 13<script> 14 15 export default { 16 name: 'detail', 17 props: ['questions'], 18 created() { 19 axios.get('http://localhost:3000/question/{q_id}', { 20 params: { 21 q_id: question.question.q_id 22 } 23 }) 24 .then(function(response) { 25 console.log(response); 26 this.question = response.data 27 }) 28 .catch(function(response) { 29 console.log(error) 30 }); 31 } 32 } 33</script>
###詳細ページの編集中、リストから受け取ったq_idが組み込めず…
this.$route.params.q_idという便利なアクセス手法があるとのこと。
これを利用してAPIの{q_id}に値を組み込めば簡単に行くのではないかと思ったものの、苦戦しています。Vue Devtoolを見る限り、詳細ページは確かにリストからq_idのパラメータを受け取っているものの、活用することがなかなかできません。
少し理解が追いついていない現状ですが、現在のコードは下記のようになっています。
(詳細用ページ)
javascript
1<template> 2 <div class="detail"> 3 <div v-if="question != null"> 4 <h2>{{ question.q_body }}</h2> 5 </div> 6 7 <div v-else> 8 <p>No Page.</p> 9 </div> 10 </div> 11</template> 12 13<script> 14 import axios from 'axios'; 15 16 export default { 17 name: 'detail', 18 data() { 19 return { 20 question: null 21 } 22 }, 23 mounted() { 24 this.getQuestion(this.q_id).then(question => this.question = question); 25 }, 26 beforeRouteUpdate(to, from ,next) { 27 this.getQuestion(to.params.q_id).then(question => this.question = question); 28 next(); 29 }, 30 methods: { 31 getQuestion(q_id) { 32 return axios.get("http://localhost:3000/question/", { 33 params: { 34 q_id: this.$route.params.q_id 35 } 36 }) 37 .then(function (response) { 38 question = response.data 39 }) 40 .then(function (error) { 41 console.log("http request denied"); 42 }); 43 } 44 } 45 } 46</script>
※まだ使い方をよく理解してはいませんが、beforeRouteUpdateがwatchと同じような働きをするとのことなので、参考にしたサイトに習ってそのまま取り入れています。
一応上記のコードを実行するとコンソールに
GET http://localhost:3000/question/?q_id=h28s002 404 (Not Found)
と表示されるので、「惜しいのかな?」とも考えています。
Axiosのドキュメントを参考にしたparamsの指定では、APIのURLと違ってしまうので、この点を上手く修正すれば、とりあえずAPIを上手く発火できそうな気がします。(もっとシンプルな方法がある気がしてならないけど…)
コードからもわかるとおり混乱中です。修正を続けていますが、具体的な修正案などがあればありがたいです。「リストから取得したq_idを、詳細情報取得用のAPIに組み込んで、その内容を表示する」ということがしたいです。
よろしくお願いします。
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
退会済みユーザー
2017/08/18 17:38
2017/08/18 17:55 編集
退会済みユーザー
2017/08/19 18:15
退会済みユーザー
2017/08/20 03:17