JavaScript
QiitaAPI
vue.js
lodash
adventcalendar2018
TOWNDay 8

[Vue.js] 監視プロパティを用いた非同期処理

はじめに

TOWN Advent Calendar 2018 8日目の投稿です。

学生1人目の記事ということで謎のプレッシャーですが頑張りたいと思います!

今回の記事はUdemyで学習した内容を元に、調べながら要点をまとめた記事になります。

qiitaのAPIを利用したリアルタイム検索について書きました。

完成品

See the Pen WLevzJ by JunpeiKawamura (@peijun333) on CodePen.

試しに検索バーにJavaなどを入力してみてください。
waiting for you stop typing...と表示されて入力が終わるとqiitaの検索結果がリンク付きで表示されるかと思います。
これはウォッチャと呼ばれるオプションでデータが変わるのに応じて非同期処理を行います。
コストの高い処理を実行したいときに便利です。

htmlファイルの解説

index.html
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="utf-8">
    <title>Real time search</title>
  </head>
  <body>
    <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>
        </li>
      </ul>
    </div>

    <script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/axios@0.18.0/dist/axios.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/lodash@4.17.10/lodash.min.js"></script>
    <script src="js/main.js"></script>
  </body>
</html>

マスタッシュ構文

Vue.jsは {{}}マスタッシュ構文で値を代入することができます。
例えば上記の {{ message }} はjsで定義されているdataオプションの配下にある、messageを表示させるという意味になります。

属性のデータバインディング

上記のようにマスタッシュ構文で href=" {{ }} " と書きたくなりますが、属性にマスタッシュ構文を使うことができません。
属性のデータバインディングにはv-bindを使います。
以下のように省略して記述することができます。

<!-- 完全な構文 -->
<a v-bind:href="url"> ... </a>

<!-- 省略記法 -->
<a :href="url"> ... </a>

JSファイルの解説

var app = new Vue({
    el: '#app',
    data: {
        items: null,
        keyword: '',
        message: ''
    },
    watch: {
        keyword: function(newKeyword, oldKeyword) {
            this.message = 'waiting for you stop typing...'
            this.debouncedGetAnswer()
        }
    },
    created: function() {
        // this.keyword = 'Java'
        // this.getAnswer()
        this.debouncedGetAnswer = _.debounce(this.getAnswer, 1000)
    },
    methods:{
        getAnswer: function() {
            if(this.keyword === ''){
                this.items = null
                this.message = ''
                return
            }

            this.message = 'Loadng...'
            var vm = this
            var params = { page: 1, per_page: 10, 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.messae = 'Error!' + error
            })
            .finally(function() {
                vm.message = ''
            })
        }
    }
})

フォームを監視する

watchオプション

  • 値が変化するたびに呼ばれる。しかしAPIに過剰に負荷がかかってしまう...

負荷がかからないようにdebounce関数を利用する

プロパティが変化するたびに発火されても困るのでLodashのdebounce関数を使います。
debounceの使い道として値が入力しおわった時点で呼びたいときなどに使えます。
wait時間はミリセカンドで指定してください。下記の場合は1秒動きが止まったら関数が呼ばれます。

_.debounce(関数, wait時間)
this.debouncedGetAnswer = _.debounce(this.getAnswer, 1000)

created

Vue.jsのマウントは調べると大量にでてきますが、今回はDOMにアクセスしていないため、createdを仕様しています。

参照

https://lodash.com/docs/4.17.11
https://jp.vuejs.org/v2/guide/
https://qiita.com/kimullaa/items/2bf8948dffb8c52d2b6b
https://qiita.com/waterada/items/986660d31bc107dbd91c
https://www.udemy.com/learn-vuejs/