API REST OpenWeather com Vue.js

Consumir API REST OpenWeather com Vue.js
Voltar

Material complementar:

  • Conteúdo no YouTube: Acesse
  • Conteúdo gratuito e com certificado na Udemy: Acesse

Objetivo

Consumir, via Vue.js, API REST online OpenWeather. Necessário criar conta no OpenWeather, para obter chave de conexão da API.


Passo a passo

  1. Criar projeto: vue create apiClima
  2. Acessar projeto: cd apiClima
  3. Instalar Axios: npm install axios
  4. Criar arquivos (components) abaixo
  5. Executar projeto: npm run serve

components/Weather.vue


<template>
    <div>
        <input 
            v-model="city" 
            placeholder="Nome da cidade" 
            @input="fetchWeatherForecast" 
        />

        <div v-if="forecast" class="forecast-info">
            <section>
                <h2>Cidade:</h2>
                <p>Nome: {{ forecast.city.name }}</p>
                <p>País: {{ forecast.city.country }}</p>
                <p>Latitude: {{ forecast.city.coord.lat }}</p>
                <p>Longitude: {{ forecast.city.coord.lon }}</p>
                <p>População: {{ forecast.city.population }}</p>
                <p>Fuso Horário: {{ forecast.city.timezone }}</p>
                <p>Nascer do Sol: {{ formatDateTime(forecast.city.sunrise, true) }}</p>
                <p>Pôr do Sol: {{ formatDateTime(forecast.city.sunset, true) }}</p>
            </section>

            <section>
                <h2>Previsão:</h2>
                <div v-for="item in forecast.list" :key="item.dt" class="forecast-item">
                    <p>Data e Hora: {{ formatDateTime(item.dt, true) }}</p>
                    <p>Temperatura Atual: {{ item.main.temp }} °C</p>
                    <p>Sensação Térmica: {{ item.main.feels_like }} °C</p>
                    <p>Temperatura Mínima: {{ item.main.temp_min }} °C</p>
                    <p>Temperatura Máxima: {{ item.main.temp_max }} °C</p>
                    <p>Pressão Atmosférica: {{ item.main.pressure }} hPa</p>
                    <p>Umidade: {{ item.main.humidity }}%</p>
                    <p>Descrição do Clima: {{ item.weather[0].description }}</p>
                    <img :src="getWeatherIcon(item.weather[0].icon)" :alt="item.weather[0].description" />
                    <p>Nuvens: {{ item.clouds.all }}%</p>
                    <p>Velocidade do Vento: {{ item.wind.speed }} m/s</p>
                    <p>Direção do Vento: {{ item.wind.deg }}°</p>
                    <p>Precipitação (3h): {{ item.rain?.['3h'] || 'Sem Dados' }} mm</p>
                    <p>Visibilidade: {{ item.visibility }} metros</p>
                    <p>Probabilidade de Precipitação: {{ item.pop * 100 }}%</p>
                    <hr>
                </div>
            </section>
        </div>

        <div v-else-if="errorMessage" class="error-message">
            <p>{{ errorMessage }}</p>
        </div>
    </div>
</template>

<script>
    import axios from "axios";

    export default {
        data() {
            return {
                city: "",
                forecast: null,
                errorMessage: null,
            };
        },
        methods: {
            async fetchWeatherForecast() {
                if (!this.city.trim()) {
                    this.forecast = null;
                    this.errorMessage = "Digite o nome de uma cidade para buscar.";
                    return;
                }

                const apiKey = "SUA_CHAVE_API";
                const url = `https://api.openweathermap.org/data/2.5/forecast?q=${this.city}&appid=${apiKey}&units=metric&lang=pt_br`;

                try {
                    const response = await axios.get(url);

                    if (response.status === 200 && response.data.cod === "200") {
                        this.forecast = response.data;
                        this.errorMessage = null;
                    }
                } catch (error) {
                    this.forecast = null;

                    if (error.response) {
                        const apiMessage = error.response.data.message;
                        this.errorMessage = apiMessage === "city not found" 
                            ? "Cidade não encontrada. Verifique o nome e tente novamente." 
                            : apiMessage || "Erro ao buscar cidade.";
                        } else if (error.request) {
                            this.errorMessage = "Nenhuma resposta recebida. Verifique a conexão.";
                        } else {
                            this.errorMessage = "Erro inesperado ao buscar dados.";
                        }
                    console.error("Erro ao buscar a API:", error);
                }
            },
            formatDateTime(dateTime) {
                return new Date(dateTime * 1000).toLocaleString("pt-BR", {
                    dateStyle: "short",
                    timeStyle: "short",
                });
            },
            getWeatherIcon(icon) {
                return `https://openweathermap.org/img/wn/${icon}@2x.png`;
            },
        },
    };
</script>

<style>
    .forecast-info {
        font-family: Arial, sans-serif;
        margin-top: 20px;
    }
    .error-message {
        color: red;
        font-weight: bold;
    }
    .forecast-item {
        margin-bottom: 20px;
    }
</style>

App.vue


<script setup lang="ts">
    import Weather from './components/Weather.vue';
</script>

<template>
    <h1>Previsão do tempo</h1>
    <Weather/>
</template>

<style>
</style>

Elaborado por Mateus Schwede
ubsocial.github.io