<aside> <img src="/icons/arrow-northeast_gray.svg" alt="/icons/arrow-northeast_gray.svg" width="40px" />

Índice

</aside>

<aside> <img src="/icons/notion_green.svg" alt="/icons/notion_green.svg" width="40px" />

Conteúdos

Introdução

Introdução ao Vue.js

Anatomia de um componente .vue

Interpolação e reatividade com ref e computed

Diretivas: v-bind, v-on, v-if, v-for e v-model

Componentes e props

Slots, emits e ciclo de vida

Introdução ao Nuxt.js

Criando o projeto Gumball Verse

Primeira requisição com useFetch

Rotas a partir de arquivos

Layout, base do projeto e nuxt.config.ts

Consumindo a API nas listagens

Páginas de detalhes com rotas dinâmicas

Tratando o erro 404 com createError

Títulos das páginas com useHead

Filtros, paginação e busca com debounce

Desafio: título e favicon dinâmicos

Conclusão e próximos passos

</aside>

Agora vamos integrar a API nas rotas de detalhes de personagem e de lugar. A ideia é juntar duas coisas que já conhecemos: a rota dinâmica com useRoute e o useFetch. O id que vem da URL vira parte do endereço da API.


Detalhes do personagem

Abra o arquivo app/pages/characters/[id].vue e substitua o conteúdo por:

<script setup>
const route = useRoute();

const { id } = route.params;

const { data } = await useFetch(`https://gumball-api-server.vercel.app/characters/${id}`);
</script>

<template>
    <section class="section section--details">
        <div class="container">
            <BackLink to="/characters">Todos os personagens</BackLink>

            <CharacterDetails
                :name="data.name"
                :full-name="data.fullName"
                :image="data.image"
                :description="data.description"
                :role="
                    data.role === 'main'
                        ? 'Principal'
                        : data.role === 'minor'
                          ? 'Secundário'
                          : 'Coadjuvante'
                "
                :status="
                    data.status === 'alive'
                        ? 'Vivo'
                        : data.status === 'deceased'
                          ? 'Morto'
                          : 'Morto-vivo'
                "
                :species="data.species"
                :gender="data.gender"
                :age="data.age ? `${data.age} anos` : 'Desconhecida'"
                :occupation="data.occupation"
                :animation-style="data.animationStyle"
                :first-appearance-code="data.firstAppearance?.code"
                :first-appearance-title="data.firstAppearance?.title"
                :aliases="data.aliases"
                :voice-actors="data.voiceActors"
                :colors="data.colors"
                :color="getCharacterColor(data.colors)"
            />
        </div>
    </section>
</template>

Entendendo o código

<aside> 💡 Os ternários encadeados funcionam como um if / else if / else em formato de expressão. Por exemplo: se o papel for main, é Principal; senão, se for minor, é Secundário; senão, é Coadjuvante.

</aside>


Detalhes do lugar

Agora abra o arquivo app/pages/locations/[id].vue e substitua o conteúdo por:

<script setup>
const route = useRoute();

const { id } = route.params;

const { data } = await useFetch(`https://gumball-api-server.vercel.app/locations/${id}`);
</script>

<template>
    <section class="section section--details">
        <div class="container">
            <BackLink to="/locations">Todos os lugares</BackLink>

            <LocationDetails
                :name="data.name"
                :image="data.image"
                :description="data.description"
                :type="data.type"
                :parent-id="data.parent?.id"
                :parent-name="data.parent?.name"
                :first-appearance-code="data.firstAppearance?.code"
                :first-appearance-title="data.firstAppearance?.title"
            />
        </div>
    </section>
</template>

A lógica é a mesma: pegamos o id da URL, buscamos o lugar na API e passamos os dados como props para o componente LocationDetails. Repare no uso do ?. em parent e firstAppearance, que podem não existir em todos os lugares.


Testando