LoginSignup
10

More than 3 years have passed since last update.

【Vue.js】QiitaのAPIを使ったリアルタイム検索プログラムの作成方法

Last updated at Posted at 2020-08-05

【Vue.js】QiitaのAPIを使ったリアルタイム検索プログラムの作成方法

任意の検索KWを入力すると、該当するQiitaの最新20記事のタイトル、リンク、LGTM数を一覧で表示するプログラムの作成方法。

何かをDLしたりインストールする必要がない。ファイルもHTMLファイルとjsファイルの2つだけあれば作成可能。

▼完成図(ブラウザの表示例)

image.png

目次

  1. 使用するAPI
  2. 実装する機能
  3. 利用するソフトウェア
  4. ソフトウェアの読み込み
  5. オプションの用意
  6. dataオプションの準備
  7. methodsオプションの準備
    1. APIデータ取得条件の設定
    2. axiosの取得条件の設定
  8. createdオプションの準備
    1. createdオプションとは?(Vueライフサイクルの理解)
    2. createdの記述
    3. lodashとは?
    4. debounceとは?
  9. テンプレートの作成
  10. watchオプションの作成
  11. 完成版

実装する機能

  • 検索窓の設置。
  • 入力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)
- 説明:https://qiita.com/api/v2/docs#get-apiv2items
- APIエンドポイント:https://qiita.com/api/v2/items

▼APIの種類は下記ページがわかりやすい。
https://qiita.com/tag1216/items/b0b90e30c7e581aa2b00

<注意点>
リクエスト回数制限あり
・認証しているユーザー:1時間に1000回まで
・非認証ユーザー: 1時間に60回まで

利用するソフトウェア

  1. Vue.js
  2. Qiita API v2
  3. HTTPクライアント axios
  4. ユーティリティライブラリ lodash
  • axios: 指定したURLのデータを取得するツール
  • lodash: キーボード入力完了まで処理を待機するツールdebounceのライブラリ

ソフトウェアの読み込み

htmlファイルのbodyタグ上にCDNのURLを貼り付け。

.html
    <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つ。

  1. el
  2. data
  3. watch
  4. created
  5. methods
空のオプションを準備
var app1 = new Vue({
    el: '#app',
    data: {

    },
    watch:{

    },
    //HTTPリクエスト用。mountedでも可。DOMにアクセスする必要がなければcreatedの方が早い
    created: function(){

    },
    methods:{

    }
})

dataオプションの準備

3つのプロパティを準備する。

  1. items: APIから取得した検索結果を格納
  2. keyword: 検索クエリ
  3. message: ユーザーへの表示内容
dataオプション
data: {
        items: null,
        keyword: '',
        message: ''
    }

methodsオプションの準備

  1. axiosでAPIを叩きデータを取得するメソッド
  2. 検索クエリが未入力の場合はAPIを叩かない(処理終了)
  3. エラー発生時の処理
  4. データロード時の表示(Loading...)
methodオプション
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

image.png

(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を使用する。

Vue公式ページのライフサイクル図

image.png

createdの記述

<デバッグ用>
1. 検索クエリのセット
2. APIを叩く(getAnswer)メソッドを実行

.js
    //初期実行動作。el読み込み前のタイミングで以下処理を実行する。
    created: function(){
        this.keyword = 'JavaScript'
        this.getAnswer()

<本番用>
上記2つをコメントアウトし、lodashライブラリのdebounce関数を設定する。

指定時間経過後に、APIを叩くgetAnswerメソッドを実行するプログラム。

getAnswerは検索ボックスが空白の時、if文で実行しないようになっている。(初回ロード時は何も発生しない)

.js
   //初期実行動作。el読み込み前のタイミングで以下処理を実行する。
    created: function(){
        // this.keyword = 'JavaScript'
        // this.getAnswer()
        this.debouncedGetAnswer = _.debounce(this.getAnswer, 6000)

lodashとは

JavaScriptの便利な関数をまとめたライブラリ。
lodashの機能一覧

lodashはVue同様CDNを読み込めば使える。

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数)
.html
    <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オプションの作成

検索ボックスに新しいキーワードが入力されたら、表示を自動更新する。

  1. タイピング中に表示するメッセージの作成
  2. タイピング終了まで待機し、終了後にAPIへのリクエストメソッドを実行
watchオプション
 watch:{
        keyword: function(newKW, oldKW){
            //文字入力中にメッセージを表示
            this.message = 'Waitting 6 seconds for your typping...'
            //作成したgetAnswerメソッドを実行する
            this.debouncedGetAnswer()
        }

リクエスト回数上限があるため、6秒間待機するよう設計している。


完成版

.js
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 = ''
            })
        }

    }
})
.html
<!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>



以上。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10