Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

This article is a Private article. Only a writer and users who know the URL can access it.
Please change open range to public in publish setting if you want to share this article with other users.

vue入門05(APIを用いたリアルタイムサーチ・監視プロパティへの理解を深める)

Last updated at Posted at 2024-06-03

APIを用いたリアルタイムサーチ

  • Qiitaの投稿検索APIを使って、記事のリアルタイムサーチを制作する。
  • Vue.jsの監視プロパティ(ウォッチャ)の使い方の理解を深める

利用するAPI

注意事項

  • 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')

スクリーンショット 2024-06-03 230432.png

  • 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>

スクリーンショット 2024-06-03 233831.png

  • リストが表示される
<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)
    }
  },

スクリーンショット 2024-06-04 004439.png

  • キーワードに入力するたび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()
    }
  },
  • keywordの値に変化があったらタイピング中の表示をしておく

    実装確認

    スクリーンショット 2024-06-04 005827.png
    スクリーンショット 2024-06-04 005848.png
    スクリーンショット 2024-06-04 005910.png

  • 文字を入力して入力をやめる

  • APIをたたいて画面に結果が表示される

  • 検索キーワードを追加するとそちらも反映される

0

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?