Vue.jsとaxios、InfiniteLoadingを使用してリアクティブなSPAサイトを作成する

NewsAPIプログラミング

NUXT等使用せずに単純なSPAを作成してみました。

参考になるプラグインとしては、axiosやInfiniteLoadingを使用しているので現在これらを学習中の人の参考になればと思います。

Githubページに公開しているので確認してみてください。

スポンサーリンク

概要

APIは2種類を使い分けています。(※axios使用部分)

  • News API
  • HackerNewsAPI

そして、20件ずつ画面に表示して残りはページ下部までスクロールをした時に追加で読み込むように実装しています。(※vue-infinite-loading使用部分)

CSSを一から書くのはしんどいのでCSSフレームワークには”Bulma”を使用しています。

単純なVueプロジェクトを作成する

ここら辺は公式ドキュメント通りで作成してます。

$ vue create <プロジェクト名>

package.jsonの中身

"dependencies": {
    "axios": "^0.19.2",
    "bulma": "^0.8.0",
    "core-js": "^3.4.4",
    "sass": "^1.25.0",
    "sass-loader": "^8.0.2",
    "vue": "^2.6.10",
    "vue-infinite-loading": "^2.4.4"
  },
  "devDependencies": {
    "@vue/cli-plugin-babel": "^4.1.0",
    "@vue/cli-plugin-eslint": "^4.1.0",
    "@vue/cli-service": "^4.1.0",
    "babel-eslint": "^10.0.3",
    "eslint": "^5.16.0",
    "eslint-plugin-vue": "^5.0.0",
    "vue-template-compiler": "^2.6.10"
  },

最低限必要なのは”axios”、”vue-infinite-loading”です。Vue用に使用できるパッケージがあるので、”infinite-loading”より”vue-infinite-loading”がお勧めです。

API切り替えボタンの実装

radioボタンを2種類準備します。それぞれを選択した時に”this.selectAPI”が選択したradioボタンの”value”になります。そのため、@change=”selectAPI”でメソッドselectAPI()を呼んでどちらのAPIを使うかフラグを立てています。

  • “NewAPIを使う”を選択した場合、isNewsAPIがtrueになります。
  • “HackerNewsAPIを使う”を選択した場合、isHackerNewsAPISelectがtrueになります。
// App.vue(Template ※API切り替えボタン部分)
<template>
<!-- API切り換えボタン -->
〜〜〜〜
<input type="radio" v-model="selectApi" value="isNewsAPI" @change="selectAPI" />
<label>NewsAPIを使う</label>
〜〜〜〜
<label class="radio">
<input type="radio" id="two" v-model="selectApi" value="isHackerNewsAPISelect" @change="selectAPI"/>
<label>HackerNewsAPIを使う</label>
〜〜〜〜
</template>

APIに渡すパラメータのプルダウンリストの表示・非表示

上記部分で選択したradioボタンによってフラグがtrueになった方を表示します。

  • “NewAPIを使う”を選択した場合、isNewsAPIがtrueになるため、v-if=”isNewsAPI”の内部部分が表示されます。
  • “HackerNewsAPIを使う”を選択した場合、isHackerNewsAPISelectがtrueになるため、v-if=”isHackerNewsAPISelect”の内部部分が表示されます。
// App.vue(Template部分 ※API表示部分)
    <!--NewsAPI-->
    <nav v-if="isNewsAPI">
〜〜〜〜
          <span>used by NewsAPI</span>
〜〜〜〜
            <select v-model="country" @change="changeType">
              <option>jp</option>
              <option>us</option>
            </select>
〜〜〜〜
            <select v-model="category" @change="changeType">
              <option>business</option>
              <option>entertainment</option>
              <option>general</option>
              <option>health</option>
              <option>science</option>
              <option>sports</option>
            </select>
〜〜〜〜
    <div class="flexbox" v-if="isNewsAPI">
      <div class="flexboxchild" v-for="(result, $index) in results" v-bind:key="$index">
        <figure class="image is-4by3">
          <img v-bind:src="result.urlToImage" />
        </figure>
        <p class="title">{{result.title}}</p>
        <p>{{result.content}}</p>
〜〜〜〜
    <!--HackerNewsAPI-->
    <nav v-if="isHackerNewsAPISelect">
〜〜〜〜
          <span>used by HackerNewsAPI</span>
〜〜〜〜
            <select v-model="tags" @change="changeType">
              <option>story</option>
              <option>poll</option>
              <option>show_hn</option>
              <option>ask_hn</option>
              <option>front_page</option>
            </select>
〜〜〜〜
    <div v-if="isHackerNewsAPISelect">
      <div v-for="(result, $index) in results" v-bind:key="$index">
        <div>
          {{ $index + 1 }}.▲
          <p class="title">{{result.title}}</p>
        </div>
        <div>{{result.points}} points by {{result.author}} {{ result.created_at}}</div>

infiniteloadingによって表示する部分の実装(ほぼそのまま)

@infinite=”infiniteHandler”部分でメソッドinfiniteHandler()を呼んでいます。

フラグがtrueの方がaxiosによって実行され結果が表示されます。

// App.vue(Template部分 ※infiniteloading表示部分)
    <!--infiniteloading-->
    <infinite-loading
      ref="infiniteLoading"
      spinner="spiral"
      :identifier="infiniteId"
      @infinite="infiniteHandler"
    >
      <div slot="spinner">Loading...</div>
      <div slot="no-more">API Limit.</div>
      <div slot="no-results">No results</div>
    </infinite-loading>
NewsAPI
NewsAPI使用時の表示内容

javascript部分

// App.vue(script部分※抜粋)
<script>
import axios from "axios";
import InfiniteLoading from "vue-infinite-loading";

export default {
  name: "app",
  data() {
    return {
      isActive: false,
      isNewsAPI: false
    };
  },
  methods: {
    infiniteHandler() {
      if (this.isHackerNewsAPISelect == true) {
        axios.get(hackerNewsAPI
            〜〜〜
      } else if (this.isNewsAPI == true) {
        axios.get(newsAPI
        〜〜〜
      } else {
        this.$refs.infiniteLoading.stateChanger.complete();
      }
    },
    changeType() {
〜〜〜〜
    },
    selectAPI() {
      if (this.selectApi == "isHackerNewsAPISelect") {
        this.isNewsAPI = false;
        this.isHackerNewsAPISelect = true;
      } else {
        this.isNewsAPI = true;
        this.isHackerNewsAPISelect = false;
      }
    }
  }

</script>
HackerNewsAPI
HackerNewsAPI使用時の表示内容

Githubページに公開しているので確認してみてください。

コメント