yonemoto

お天気アプリで学ぶVue.jsのAPI連携

Vue.js で気象情報を表示させてみたいなとふと思い立ったので実際に作りながらVue.jsのAPI連携についてもまとめてみました。

今回実装するに当たってAPIからデータの取得が簡単に行えるaxiosを利用します。
基本的なVue.jsの使い方は公式ドキュメントがあります。
Vue.js - 基本的な使い方

axiosに関してより詳しく知りたいという方は以下のリンク先でご確認ください。
GitHub - axios/axios: Promise based HTTP client for the browser and node.js

■以下のように特定地域の気象情報をVue.jsで描画させることを目指します。

デモページ

■必要な準備
OpenWeatherMapでアカウント(無料)を作成し、APIキーを取得する
OpenWeatherMapでは気象情報を取得できるAPIサービスが用意されており、現在の気象情報と5日間の3時間毎の予報まで無料で取得することができます。(2018/09/03時点)

今回は大阪の気象情報を取得して表示させてみることにします。q="都市名"で地域を指定することができます。詳しくはOpenWeatherMapのAPIドキュメントでご確認ください。

取得できたら以下のリンクで気象情報を取得してみましょう。"APIキー"にはOpenWeatherMapで取得したAPIキーを入力してください。
https://api.openweathermap.org/data/2.5/weather?q=Osaka,jp&units=metric&appid="APIキー"

1. Vueインスタンスの作成とHTMLファイルの準備

まずはVue.jsを扱う準備をして行きましょう。Vueインスタンスを作成し、city, tempといったようにOpenWeatherMapのAPIから取得する情報を格納する場所(dataプロパティ)を作っておきます。一旦、適当な値を入れておきます。ここではapp.jsとして保存します。

var app = new Vue({
  el: '#app',
  data: {
    city: 'Tokyo', //地域名
    temp: 25, //気温
    condition: {
      main: 'Rain' //天候名
    }
  }
})

HTMLファイルを準備します。
HTMLファイルにはCDNでvue.jsとaxios、そして先ほど用意したjsファイルを読み込ませます。
APIからデータを取得し、表示するにはいくつかの方法がありますがここではaxiosをCDNで読み込ませて利用します。

<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script src="app.js"></script>

次にHTMLタグの中にdataプロパティの値を表示させていきます。
Vue.js では {{ city }} のように二重中括弧の中にプロパティ名を入れて値を表示させます。

また次のようにプロパティ名の後にパイプ( | )でつないで記述されている箇所がありますがこれは
filtersというプロパティを使用する際に使います。(詳しくは後述)
{{ temp | roundUp }}

Vue.jsには v-if, v-else-if, v-else といった要素があり、これらを利用することで条件分岐を簡単に作ることができます。tureで表示、falseで非表示です。ここでは、APIから取得した値がRain, Clouds, Clearの場合はそれぞれ天候に応じた画像を表示させ、それ以外の場合は sunset.jpg という画像を表示させるようにしています。

<p v-if="condition.main == 'Rain'"><img src="img/rain.jpg" alt="Rainy"></p>
<p v-else-if="condition.main == 'Clouds'"><img src="img/cloudy.jpg" alt="Cloudy"></p>
<p v-else-if="condition.main == 'Clear'"><img src="img/sunny.jpg" alt="Sunny"></p>
<p v-else><img src="img/sunset.jpg" alt="Sunset"></p>

まとめるとHTMLファイルは以下のようになります。

<body>
  <h1>Weather Forcast</h1>
  <div id="app" class="weather_box">
    <div class="weather_info">
      <p class="weather_city">{{ city }}</p>
      <p class="weather_condition">{{ condition.main }}</p>
      <p class="weather_temp">{{ temp | roundUp }}&deg;C</p>
    </div>
    <p v-if="condition.main == 'Rain'"><img src="img/rain.jpg" alt="Rainy"></p>
    <p v-else-if="condition.main == 'Clouds'"><img src="img/cloudy.jpg" alt="Cloudy"></p>
    <p v-else-if="condition.main == 'Clear'"><img src="img/sunny.jpg" alt="Sunny"></p>
    <p v-else><img src="img/sunset.jpg" alt="Sunset"></p>
  </div>
  <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
  <script src="app.js"></script>
</body>

では実際に作成したHTMLファイルを開いて確認してみましょう。
app.jsで記述した内容がうまく表示されました。(*画像の準備、CSSによる装飾は各自でお願いします)

2. APIから気象情報を取得

今度はAPIから気象情報を取得し、インタラクティブに天候に関するテキストや画像が変わるようにしていきたいと思います。
まず先ほど適当な値を入れたdataプロパティをnullで一旦空にします。

var app = new Vue({
  el: '#app',
  data: {
    city: null, 
    temp: null, 
    condition: {
      main: null 
    }
  }
})

axiosを利用しAPIから返されるJSONファイルの情報を取得します。また取得した値を利用できるように bind します。念のため通信エラーが起こった際になんらかの処理が行われるよう catch を用います。

 mounted: function(){
    axios.get('https://api.openweathermap.org/data/2.5/weather?q=Osaka,jp&units=metric&appid="APIキー"')
    .then(function(response){
      this.city = response.data.name
      this.temp = response.data.main.temp
      this.condition = response.data.weather[0]
    }.bind(this))
    .catch(function(error){
      console.log(error)
    })
  }

filtersプロパティを利用し、気温の小数点以下を切り上げで表示させるようにします。
使い方はマスタッシュ構文の中でプロパティ名をパイプ( | )でつなぎフィルター名を記述することで値に処理を加えることができます。(例){{ temp | roundUp }}

filters: {
    roundUp(value){
      return Math.ceil(value) //小数点以下を切り上げ
    }
  }

app.js をまとめると以下のようになります。

var app = new Vue({
  el: '#app',
  data: {
    city: null,
    temp: null,
    condition: {
      main: null
    }
  },
  mounted: function(){
    axios.get('https://api.openweathermap.org/data/2.5/weather?q=Osaka,jp&units=metric&appid="APIキー"')
    .then(function(response){
      this.city = response.data.name
      this.temp = response.data.main.temp
      this.condition = response.data.weather[0]
    }.bind(this))
    .catch(function(error){
      console.log(error)
    })
  },
  filters: {
    roundUp(value){
      return Math.ceil(value)
    }
  }
})

Vue.js やっぱり便利ですね〜。簡単にお天気アプリっぽいものが作れちゃいました。

■参考

新しいウェブ体験を作ろう TAMのPWA開発
お問い合わせはこちら