Consumir API REST NASA com Vue.js

Consumir API REST de imagens da NASA com Vue.js
Voltar

Material complementar:


Contexto:

Projeto frontend Vue.js para consumir API REST da NASA para visualização da imagem destaque do dia, utilizando tecnologias Vue 3 Composition API com Vue Router, TypeScript com Volar, Vite, Axios, ESLint e Pinia.


Instalação do projeto:

  1. Em api.nasa.gov, em Generate API Key, preencher dados para gerar chave (key) de autenticação, que será enviada no email cadastrado;
  2. Criar repositório no GitHub 'Projeto API REST NASA com Vue.js';
  3. Repositório no GitHub, criar Codespaces;
  4. No terminal do Codespace, criar projeto Vite: npm create vite@latest nasa-vue-app
    • Selecionar 'Vue' e 'TypeScript' e YES para instalar dependências npm.
  5. Entrar na pasta do projeto e criar pastas faltantes: cd nasa-vue-app && mkdir src/services src/composables src/router src/store src/types src/views
  6. Instalar dependências:
    • npm install axios pinia vue-router
    • npm install -D vue-tsc eslint prettier
    • npm install -D eslint-plugin-vue @typescript-eslint/parser @typescript-eslint/eslint-plugin
  7. Criar arquivo '.env' na pasta raiz do projeto e inserir código:
    
    VITE_NASA_API_KEY=SUA_CHAVE_DE_API_NASA
    
  8. Codificar arquivos do projeto, conforme abaixo;
  9. Executar o projeto: npm run dev

Arquivos do projeto:

  • vite.config.ts:
    
    import { defineConfig } from "vite";
    import vue from "@vitejs/plugin-vue";
    import path from "path";
    
    export default defineConfig({
        plugins: [vue()],
        resolve: {
            alias: {
                "@": path.resolve(__dirname, "./src"),
            },
        },
    });
    
  • src/services/api.ts:
    
    import axios from "axios";
    
    export const api = axios.create({
        baseURL: "https://api.nasa.gov",
    });
    
  • src/services/nasaService.ts:
    
    import { api } from "./api";
    
    const API_KEY = import.meta.env.VITE_NASA_API_KEY;
    
    export const getApod = async () => {
        const response = await api.get("/planetary/apod", {
            params: { api_key: API_KEY },
        });
        return response.data;
    };
    
  • src/types/Apod.ts:
    
    export interface Apod {
        title: string;
        explanation: string;
        url: string;
        date: string;
    }
    
  • src/composables/useApod.ts:
    
    import { ref, onMounted } from "vue";
    import { getApod } from "@/services/nasaService";
    import type { Apod } from "@/types/Apod";
    
    export function useApod() {
        const data = ref<Apod | null>(null);
        const loading = ref(true);
        const error = ref<string | null>(null);
    
        const fetchApod = async () => {
            try {
                data.value = await getApod();
            } catch (err) {
                error.value = "Erro ao carregar dados";
            } finally {
                loading.value = false;
            }
        };
    
        onMounted(fetchApod);
        return { data, loading, error };
    }
    
  • src/router/index.ts:
    
    import { createRouter, createWebHistory } from "vue-router";
    import HomeView from "@/views/HomeView.vue";
    
    const routes = [
        { path: "/", component: HomeView },
    ];
    
    export const router = createRouter({
        history: createWebHistory(),
        routes,
    });
    
  • src/store/index.ts:
    
    import { createPinia } from "pinia";
    
    export const pinia = createPinia();
    
  • main.ts:
    
    import { createApp } from "vue";
    import App from "./App.vue";
    import { router } from "./router";
    import { pinia } from "./store";
    
    const app = createApp(App);
    
    app.use(router);
    app.use(pinia);
    app.mount("#app");
    
  • src/views/HomeView.vue:
    
    <script setup lang="ts">
    import { useApod } from "@/composables/useApod";
    
    const { data, loading, error } = useApod();
    </script>
    
    <template>
        <div>
            <h1>NASA (Foto do Dia):</h1>
    
            <div v-if="loading">Carregando</div>
            <div v-else-if="error">{{ error }}</div>
    
            <div v-else-if="data">
                <h2>{{ data.title }}</h2>
                <img :src="data.url" width="500">
                <p>{{ data.explanation }}</p>
            </div>
    
            <h3>JSON recebido:</h3>
            <pre v-if="data">
                {{ JSON.stringify(data, null, 2) }}
            </pre>
        </div>
    </template>
    
  • src/App.vue:
    
    <template>
        <router-view />
    </template>
    

Elaborado por Mateus Schwede
ubsocial.github.io