【Vue.js】QiitaのAPIを使ったリアルタイム検索プログラムの作成方法
任意の検索KWを入力すると、該当するQiitaの最新20記事のタイトル、リンク、LGTM数を一覧で表示するプログラムの作成方法。
何かをDLしたりインストールする必要がない。ファイルもHTMLファイルとjsファイルの2つだけあれば作成可能。
▼完成図(ブラウザの表示例)
![]() |
---|
目次
- 使用するAPI
- 実装する機能
- 利用するソフトウェア
- ソフトウェアの読み込み
- オプションの用意
- dataオプションの準備
- methodsオプションの準備
- createdオプションの準備
- テンプレートの作成
- watchオプションの作成
- 完成版
実装する機能
- 検索窓の設置。
- 入力KWの変化を自動で検知し、自動検索を実行する。
- 自動検索まで6秒間待機する(リクエスト上限があるため)
- KWに該当する最新記事のtitle, リンク(URL), LGTMの一覧を表示
- KW入力中は「Waitting 6 seconds for your typping...」を表示
- Loading中は「Loading...」を表示
- 検索窓が空白の場合は自動検索を実行しない。
使用するAPI
・API: Qiita API v2
・公式ページ:https://qiita.com/api/v2/docs
・API詳細:記事の一覧を更新日時の降順で返すAPI(GET item)
▼APIの種類は下記ページがわかりやすい。
https://qiita.com/tag1216/items/b0b90e30c7e581aa2b00
<注意点>
リクエスト回数制限あり
・認証しているユーザー:1時間に1000回まで
・非認証ユーザー: 1時間に60回まで
利用するソフトウェア
- Vue.js
- Qiita API v2
- HTTPクライアント axios
- ユーティリティライブラリ lodash
- axios: 指定したURLのデータを取得するツール
- lodash: キーボード入力完了まで処理を待機するツールdebounceのライブラリ
ソフトウェアの読み込み
htmlファイルのbodyタグ上にCDNのURLを貼り付け。
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script>
<script src="https://cdn.jsdelivr.net/npm/axios@0.19.2/dist/axios.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.19/lodash.min.js"></script>
オプションの用意
jsファイルで使用するオプションは5つ。
- el
- data
- watch
- created
- methods
var app1 = new Vue({
el: '#app',
data: {
},
watch:{
},
//HTTPリクエスト用。mountedでも可。DOMにアクセスする必要がなければcreatedの方が早い
created: function(){
},
methods:{
}
})
dataオプションの準備
3つのプロパティを準備する。
- items: APIから取得した検索結果を格納
- keyword: 検索クエリ
- message: ユーザーへの表示内容
data: {
items: null,
keyword: '',
message: ''
}
methodsオプションの準備
- axiosでAPIを叩きデータを取得するメソッド
- 検索クエリが未入力の場合はAPIを叩かない(処理終了)
- エラー発生時の処理
- データロード時の表示(Loading...)
methods:{
getAnswer: function(){
//検索クエリが空の場合は処理終了
if(this.keyword === ''){
this.items = null
//2回目以降の検索時にメッセージを空にする
this.message = ""
return
}
//ロード中の表示
vm.message = 'Loading...'
//Vueインスタンスを格納する変数を定義
var vm = this
//リクエスト条件を定義。1ページ表示、表示件数は20件、検索クエリはキーワードの入力値
var params = {page:3, per_page:20, query: this.keyword}
//axiosのgetメソッドでAPIをたたく
axios.get('https://qiita.com/api/v2/items', params)
.then(function(res){
console.log(res) //データ取得できたか確認用
this.item = res.data //itemプロパティに取得データを格納
})
//エラー発生時の処理
.catch(function(error){
vm.message = 'Error!' + error
})
//通信が完了したらLoadingの表示をクリア
.finally(function(){
vm.message = ''
})
}
}
APIデータ取得条件の設定
APIデータ要求。必要な取得条件はQiita APIの公式ページに記載されている。
axios.get('URL', 取得条件
)
取得データは「.then()」内で「functionの引数」の値に入る。
.then(function(res){処理})
APIの取得条件の確認
公式ページに記載されている3つのパラメータを記載する。
https://qiita.com/api/v2/docs#get-apiv2items
![]() |
---|
(1)page, (2)per_page, (3)queryが必要となる。
axiosの取得条件の設定
取得条件は①パラメータで直接URLに付与するか、②引数で指定することができる。
①パラメータで直接URLに付与
axios.get('https://qiita.com/api/v2/items?page=1&per_page=20&query=javascript')
②引数で指定
axios.get('https://qiita.com/api/v2/items', {page:3, per_page:20, query: this.keyword})
②'引数を変数に代入
axios.get('https://qiita.com/api/v2/items', {params})
※変数に波カッコをつける。ないと指定がない状態になってしまう。
## createdオプションの準備 ### createdオプションとは?(Vueライフサイクルの理解) jsファイル読み込み時に初期段階で実行する。 Vueインスタンス作成時のライフサイクルで、elを読み込む前の段階で実行される。
PHPなどのコンストラクターのようなイメージ。
もし、DOMを読み込む必要があれば、createdの代わりにmountedを使用する。
createdの記述
<デバッグ用>
- 検索クエリのセット
- APIを叩く(getAnswer)メソッドを実行
//初期実行動作。el読み込み前のタイミングで以下処理を実行する。
created: function(){
this.keyword = 'JavaScript'
this.getAnswer()
<本番用>
上記2つをコメントアウトし、lodashライブラリのdebounce関数を設定する。
指定時間経過後に、APIを叩くgetAnswerメソッドを実行するプログラム。
getAnswerは検索ボックスが空白の時、if文で実行しないようになっている。(初回ロード時は何も発生しない)
//初期実行動作。el読み込み前のタイミングで以下処理を実行する。
created: function(){
// this.keyword = 'JavaScript'
// this.getAnswer()
this.debouncedGetAnswer = _.debounce(this.getAnswer, 6000)
lodashとは
JavaScriptの便利な関数をまとめたライブラリ。
lodashの機能一覧
lodashはVue同様CDNを読み込めば使える。
<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.19/lodash.min.js"></script>
debounceとは
lodashに用意された関数の一つ。指定秒数経過後に、指定した関数を実行する。
キーボード入力が終わるまで待つ場合などに使える。
公式ページ:https://lodash.com/docs/4.17.15#debounce
_.debounce(func, ミリ秒)
┗ デフォルトはミリ秒 = 0
## テンプレートの作成 1. キーワード入力欄(v-modelで双方向バインディング) 2. Loadingメッセージ 3. 取得データ表示(タイトル名、リンク、LGTM数)
<div id="app">
<p>
<input type="text" v-model="keyword">
<button v-on:click="getAnswer()">検索</button>
</p>
<p>
{{ message }}
</p>
<ul>
<li v-for="item in items">
<!-- {{ item.title }} -->
<a v-bind:href=" item.url " target="_blank">{{ item.title }} </a> LGTM:{{ item.likes_count}}
</li>
</ul>
</div>
## watchオプションの作成 検索ボックスに新しいキーワードが入力されたら、表示を自動更新する。
- タイピング中に表示するメッセージの作成
- タイピング終了まで待機し、終了後にAPIへのリクエストメソッドを実行
watch:{
keyword: function(newKW, oldKW){
//文字入力中にメッセージを表示
this.message = 'Waitting 6 seconds for your typping...'
//作成したgetAnswerメソッドを実行する
this.debouncedGetAnswer()
}
リクエスト回数上限があるため、6秒間待機するよう設計している。
## 完成版
var app1 = new Vue({
el: '#app',
data: {
items: null,
keyword: '',
message: ''
},
watch:{
keyword: function(newKW, oldKW){
//文字入力中にメッセージを表示
this.message = 'Waitting 6 seconds for your typping...'
//作成したgetAnswerメソッドを実行する
this.debouncedGetAnswer()
}
},
//初期実行動作。el読み込み前のタイミングで以下処理を実行する。
created: function(){
// this.keyword = 'JavaScript'
// this.getAnswer()
this.debouncedGetAnswer = _.debounce(this.getAnswer, 6000)
},
methods:{
getAnswer: function(){
//検索クエリが空の場合は処理終了
if(this.keyword === ''){
this.items = null
this.message = ""
return
}
//ロード中の表示
this.message = 'Loading...'
//Vueインスタンスを格納する変数を定義
var vm = this
//リクエスト条件を定義。1ページ表示、表示件数は20件、検索クエリはキーワードの入力値
var params = {page:3, per_page:20, query:this.keyword}
//axiosのgetメソッドでAPIをたたく
axios.get('https://qiita.com/api/v2/items', {params})
// axios.get('https://qiita.com/api/v2/items', {page:3, per_page:20, query: this.keyword})
// axios.get('https://qiita.com/api/v2/items?page=1&per_page=20&query=javascript')
.then(function(res){
console.log(res) //データ取得できたか確認用
console.log(res.data)
console.log(vm.keyword)
vm.items = res.data //itemプロパティに取得データを格納 ※thisはNG
})
//エラー発生時の処理
.catch(function(error){
vm.message = 'Error!' + error
})
//通信が完了したらLoadingの表示をクリア
.finally(function(){
vm.message = ''
})
}
}
})
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Qiita API</title>
</head>
<body>
<div id="app">
<p>
<input type="text" v-model="keyword">
<button v-on:click="getAnswer()">検索</button>
</p>
<p>
{{ message }}
</p>
<ul>
<li v-for="item in items">
<!-- {{ item.title }} -->
<a v-bind:href=" item.url " target="_blank">{{ item.title }} </a> LGTM:{{ item.likes_count}}
</li>
</ul>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script>
<script src="https://cdn.jsdelivr.net/npm/axios@0.19.2/dist/axios.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.19/lodash.min.js"></script>
<script src="js/main.js"></script>
</body>
</html>
以上。