APIを用いたリアルタイムサーチ
- Qiitaの投稿検索APIを使って、記事のリアルタイムサーチを制作する。
- Vue.jsの監視プロパティ(ウォッチャ)の使い方の理解を深める
利用するAPI
- Qiita API v2(無料)
- APIドキュメント
https://qiita.com/api/v2/docs
注意事項
- Qiita APIは必ず利用できることが保証されたものではない。
- メンテナンス時は時間をおいて学習
- APIが廃止されたり、仕様変更が発生した場合は学習できなくなる
リクエスト回数制限
- 認証していない状態ではIPアドレスごとに1時間に60回まで(認証ユーザーは1000回)
- 実運用でこの回数では足りない可能性がある点に注意
- 過度な負荷を掛けて、迷惑をかけないようにする
利用するソフトウェアなどのバージョン
- Vue.js 3.1.5
- Qiita API v2
- HTTPクライアント axious 0.21.1
- ユーティリティライブラリ lodash 4.17.21
開発の準備
<body>
<div id="app">
</div>
<script src="https://unpkg.com/vue@3.1.5"></script>
<script src="https://unpkg.com/axios@0.21.1/dist/axios.js"></script>
<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.21/lodash.js"></script>
<script src="js/main.js"></script>
</body>
- axiosとlodashの読み込み
- サンプルーコードからコピペした
空のオプションの用意をする
const app = Vue.createApp({
data: () => ({
}),
watch:{
},
mounted: function(){
},
methods:{
}
})
app.mount('#app')
dataオプションを実装する
const app = Vue.createApp({
data: () => ({
items: null,
keyword: '',
message: ''
}),
watch:{
},
mounted: function(){
},
methods:{
}
})
app.mount('#app')
-
items
にはAPIから取得した検索結果を格納する -
keyword
にはユーザーが入力した検索キーワードを入れる -
message
にはユーザーに表示するメッセージを格納する
APIからデータを取得する
const app = Vue.createApp({
data: () => ({
items: null,
keyword: '',
message: ''
}),
watch:{
},
mounted: function(){
this.keyword = 'Javascript'
this.getAnswer()
},
methods:{
getAnswer: function(){
if(this.keyword === ''){
console.log('kawamoji')
this.items = null
return
}
this.message = 'Lading...'
const vm = this
const params = { page: 1, per_page: 20, query: this.keyword }
axios.get('https://qiita.com/api/v2/items', { params })
.then(function(response){
console.log(response)
})
.catch(function(error){
vm.message = 'Error!' + error
})
.finally(function(){
vm.message = ''
})
}
}
})
app.mount('#app')
- APIからデータを取得するメソッド
getAnswer
を実装
if(this.keyword === ''){
console.log('kawamoji')
this.items = null
return
}
- keywordプロパティが空がどうかをチェック
- keywordプロパティが空文字ならitemsをnullにしてそこで処理を終了する
this.message = 'Lading...'
- ユーザーが検索キーワードを入力している場合はローディング中のメッセージを出す
const vm = this
- axiosでVueインスタンスのプロパティにアクセスするためにthisをローカル変数に入れておく
const params = { page: 1, per_page: 20, query: this.keyword }
- axiosを使ってAPIを叩くにあたって、パラメータをキー・バリュー形式で用意する
axios.get('https://qiita.com/api/v2/items', { params })
.then(function(response){
console.log(response)
})
- axiosのgetメソッドを使ってAPIを叩く
- axiosの作者が決めたルールに従って記述する
- パラメータを渡すには第二引数に
{params}とする
- APIからデータが返ってくるとthenメソッドが呼ばれる
- 取得した値は
response
に入っている - デバックようにconsole.logで
response
を出力
.catch(function(error){
vm.message = 'Error!' + error
})
.finally(function(){
vm.message = ''
})
- 例外を取得するためのキャッチと最後に実行したい処理を書くfinally
- なんらかのエラーが発生した時は
Error!
という文字列に続いてエラーの内容をメッセージにセットする - すべて処理が終わった場合にはメッセージを空にする
mounted: function(){
this.keyword = 'Javascript'
this.getAnswer()
},
-
動作確認としてmountedでgetAnswerメソッドを呼ぶ
-
本来keyword要素はユーザーが入力するがここでは検証のために直接プロパティに
Javascript
というキーワードを代入する -
getAnswerメソッドを呼ぶ
-
dataが取得できているのでconsole.logで値が表示できている
-
data配下に複数の記事の情報が入っている
getAnswer: function(){
if(this.keyword === ''){
console.log('kawamoji')
this.items = null
return
}
this.message = 'Loading...'
const vm = this
const params = { page: 1, per_page: 20, query: this.keyword }
axios.get('https://qiita.com/api/v2/items', { params })
.then(function(response){
//console.log(response)
vm.items = response.data
})
.catch(function(error){
vm.message = 'Error!' + error
})
.finally(function(){
vm.message = ''
})
}
- APIからデータが取得できていることの確認ができたので、全メソッドの中でitemsプロパティにレスポンスデータの値を入れる
- ※thenメソッドはサーバーからデータが返ってきたときに呼ばれるメソッド
- ※デバック用のconsole.logはコメントアウトした
テンプレート側の実装
<div id="app">
<p>
<input type="text" v-model="keyword">
</p>
<p>{{ message }}</p>
<ul>
<li v-for="item in items">
{{ item.title }}
</li>
</ul>
</div>
- リストが表示される
<div id="app">
<p>
<input type="text" v-model="keyword">
</p>
<p>{{ message }}</p>
<ul>
<li v-for="item in items">
<a v-bind:href="item.url" target="_blank">
{{ item.title }}
</a>
likes: {{ item.likes_count }}
</li>
</ul>
</div>
- リンクといいね数も追加した
フォームの監視
- 検索キーワードの入力フォームの値の変化を監視して、APIを叩く処理などを実装する
watch:{
keyword: function(newKeyword, oldKeyword){
console.log(newKeyword)
}
},
- キーワードに入力するたびkeywordの値がコンソールに表示されている
- これで値が変化するたびになんらかの処理を実行できる体制が整った。
- ※ただ、値が変化するだとAPIに過剰な負荷がかかり、利用宣言もすぐに超える
- そこで、指定時間内に同じイベントが発生すると処理は実行せず、発生しなければ処理を実行するという処理を追加する
lodashのdebounce関数を使う
- vue,jsの内容から離れてきてくるので利用する
watch:{
keyword: function(newKeyword, oldKeyword){
console.log(newKeyword)
this.debouncedGetAnswer()
}
},
mounted: function(){
//this.keyword = 'Javascript'
//this.getAnswer()
this.debouncedGetAnswer = _.debounce(this.getAnswer, 1000)
},
- この記述で指定時間内に同じイベントが発生すると処理は実行せず、発生しなければ処理を実行するという処理ができていて、APIのリクエストを間引くことができる
watch:{
keyword: function(newKeyword, oldKeyword){
console.log(newKeyword)
this.message = 'Wating for you to stop typing...'
this.debouncedGetAnswer()
}
},