API REST OpenWeather com Vue.js

Consumir API REST OpenWeather com Vue.js
Voltar
Conteúdo disponível

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