Vue 3: Composition API ou Options API, para que serve realmente cada uma

  • vuetelemetry
  • Guias
  • 6 min de leitura

A Composition API não substitui a Options API. Resolvem problemas diferentes em escalas diferentes, e a escolha depende menos de qual é mais recente e mais de como o seu componente cresce. O que cada uma faz, onde cada uma mostra limites e como escolher sem reescrever código que funciona.

O Vue 3 inclui as duas API. A Options API é a que o Vue sempre teve: um componente é um objeto com `data`, `computed`, `methods`, `watch` e os hooks de ciclo de vida como propriedades com nome. A Composition API, introduzida no Vue 3, permite escrever a mesma lógica como funções normais dentro de uma função `setup()` ou de um bloco `<script setup>`. Nenhuma está obsoleta e nenhuma vai desaparecer.

A Options API organiza o código por tipo de opção. Todo o estado reativo vai para `data()`. Todos os valores calculados vão para `computed`. Todos os métodos vão para `methods`. Em componentes pequenos é claro, porque cada assunto ocupa poucas linhas em cada secção e as secções percorrem-se depressa. Torna-se um problema quando o componente cresce: uma única funcionalidade (por exemplo, um filtro de pesquisa) tem o estado em `data`, os valores derivados em `computed`, os handlers de eventos em `methods` e a inicialização em `mounted`. Fica espalhada por quatro sítios do ficheiro.

Como a Options API organiza o código

Pistas de cobre numa placa de circuito preta que partem em todas as direções de uma ilha octogonal central, rodeada de pequenos componentes de montagem em superfície etiquetados de S4 a S12.
Pistas de cobre numa placa de circuito preta que partem em todas as direções de uma ilha octogonal central, rodeada de pequenos componentes de montagem em superfície etiquetados de S4 a S12.

A Composition API organiza o código por responsabilidade lógica. Em vez de pôr todo o estado num sítio e todos os métodos noutro, agrupa-se o estado, os valores calculados, os watchers e as funções que pertencem a uma mesma funcionalidade. Um filtro de pesquisa torna-se um bloco de 15 linhas com tudo o que precisa. A paginação torna-se outro bloco. Ficam lado a lado no ficheiro, e pode ler-se um sem saltar para outras três secções.

Isto só importa em componentes grandes. Um componente com um estado, um valor calculado e um método lê-se igualmente bem com qualquer das duas API. A Composition API começa a compensar quando um componente tem três ou mais responsabilidades independentes, porque é aí que a Options API obriga a intercalar lógica sem relação entre as secções.

Como a Composition API organiza o código

`<script setup>` é a sintaxe usada pela maior parte do código novo em Vue 3. É um atalho de compilação que dispensa escrever uma função `setup()` explícita e a respetiva instrução de retorno. As variáveis declaradas no nível superior ficam automaticamente disponíveis no template. As props declaram-se com `defineProps()` e os eventos com `defineEmits()`. Ambas são macros do compilador que não é preciso importar.

  • A Options API organiza o código por tipo (data, computed, methods); a Composition API organiza-o por funcionalidade
  • Nenhuma das duas API está obsoleta, e ambas usam o mesmo sistema de reatividade
  • ref() é a escolha por omissão recomendada em vez de reactive(), para evitar erros de reatribuição e desestruturação
  • Os composables substituem os mixins para reutilizar lógica entre componentes sem colisões de nomes
  • A inferência de TypeScript funciona naturalmente com a Composition API e tem dificuldade com o this da Options API
  • A migração é opcional: as duas API coexistem no mesmo projeto e até no mesmo componente

A reatividade na Composition API usa `ref()` e `reactive()`. `ref()` envolve um único valor e exige `.value` para o ler ou escrever em JavaScript (mas não no template, onde o Vue o desembrulha automaticamente). `reactive()` envolve um objeto cujas propriedades são reativas sem `.value`. A fonte de erros mais comum é esquecer `.value` no script, ou usá-lo no template, onde não é necessário.

ref, reactive e script setup

`ref()` é quase sempre a escolha por omissão certa. `reactive()` tem duas restrições que apanham muita gente. Primeiro, não se pode reatribuir o objeto inteiro (o proxy está na referência original, não na variável). Segundo, desestruturar um objeto reativo faz perder a reatividade às propriedades extraídas. `ref()` não tem nenhum dos dois problemas, e o custo de `.value` é pequeno comparado com o tempo de depuração desses casos-limite.

Os composables são a principal vantagem estrutural. Um composable é uma função que usa as primitivas da Composition API (`ref`, `computed`, `watch`, `onMounted`) e devolve estado reativo. `useMouse()`, `useFetch()` e `useLocalStorage()` são exemplos típicos. Chamam-se em `setup()` e devolvem valores reativos. É o padrão que a Options API não consegue reproduzir de forma limpa: os mixins partilham lógica entre componentes, mas fundem as propriedades pelo nome, o que cria colisões silenciosas e impede saber de onde vem uma propriedade.

Os mixins são o equivalente na Options API, e tornam-se problemáticos em grande escala. Se dois mixins definirem uma propriedade `data` com o mesmo nome, uma delas prevalece sem aviso. Se um mixin acrescentar um método, o componente não tem nenhuma declaração visível dele. A origem de uma propriedade torna-se ambígua à medida que se juntam mixins. A documentação do Vue recomenda explicitamente os composables em vez dos mixins para reutilizar lógica no Vue 3.

Composables versus mixins

O suporte a TypeScript é claramente melhor na Composition API. A Options API precisa do invólucro `defineComponent()`, e a inferência de tipos passa por um tipo `this` complexo que tem dificuldade com certos padrões (callbacks aninhados, funções externas que leem o estado do componente). A Composition API usa variáveis normais com tipos TypeScript padrão. `ref<number>(0)` dá um `Ref<number>`. Os composables têm valores de retorno tipados. A ajuda do IDE (autocompletar, tipos ao passar o rato, refatoração) funciona como em qualquer função TypeScript.

O desempenho em execução é próximo, com duas vantagens documentadas para a Composition API. O sistema de reatividade é o mesmo nos dois casos. A documentação do Vue nota que o código em `<script setup>` se minifica melhor, porque o template é compilado numa função no mesmo âmbito e os nomes das variáveis locais podem ser encurtados, enquanto o código da Options API passa por acessos a propriedades de `this`. Um projeto que use só a Composition API pode ainda desativar a Options API com a flag de compilação `__VUE_OPTIONS_API__`, que a retira do bundle de produção. Na maioria das aplicações, estes ganhos são pequenos ao lado da forma como o código está organizado.

**O desempenho em execução é próximo, com duas vantagens documentadas para a Composition API.** O sistema de reatividade é o mesmo nos dois casos. A documentação do Vue nota que o código em `<script setup>` se minifica melhor, porque o template é compilado numa função no mesmo âmbito e os nomes das variáveis locais podem ser encurtados, enquanto o código da Options API passa por acessos a propriedades de `this`. Um projeto que use só a Composition API pode ainda desativar a Options API com a flag de compilação `__VUE_OPTIONS_API__`, que a retira do bundle de produção. Na maioria das aplicações, estes ganhos são pequenos ao lado da forma como o código está organizado.

- vuetelemetry

TypeScript, desempenho e migração

A migração não é obrigatória. O Vue 3 aceita as duas API no mesmo projeto, e no mesmo ficheiro se for preciso. Um componente Options API pode usar um composable chamando-o num método `setup()` acrescentado ao lado das opções existentes. Não é preciso reescrever componentes Options API que funcionam. O caminho prático é escrever os componentes novos com `<script setup>` e refatorar os antigos só quando já os estiver a alterar por outro motivo.

Quando escolher a Options API. Componentes pequenos ou médios com lógica simples. Equipas em que a maioria dos programadores está a aprender Vue e beneficia de uma estrutura explícita. Bases de código já escritas com a Options API que não precisam de refatoração. Prototipagem rápida, quando dar nome a refs e composables atrasa mais do que a organização ajuda.

Quando escolher a Composition API. Componentes com várias responsabilidades independentes. Qualquer situação em que seja preciso partilhar lógica com estado entre componentes (os composables substituem os mixins). Projetos com TypeScript. Bibliotecas e pacotes open source (os composables são o formato de distribuição esperado). Aplicações grandes cujos ficheiros de componentes passam com frequência das 200 linhas.

FAQ

A Options API está obsoleta no Vue 3?

Não. A equipa do Vue mantém as duas API ao mesmo nível. A Options API não está obsoleta, a sua remoção não está prevista e recebe as mesmas atualizações. A documentação apresenta as duas lado a lado. Escolher a Composition API é uma decisão sobre a organização do código, não sobre estar atualizado.

Devo reescrever os meus componentes Options API com a Composition API?

Não, a menos que haja um motivo para além da própria API. Código Options API que funciona não fica pior por existir a Composition API. O mais prático é escrever os componentes novos com a Composition API e refatorar os antigos só quando já os estiver a alterar e a refatoração facilitar a mudança.

Qual é a diferença entre ref e reactive no Vue 3?

ref() envolve um único valor e exige .value para lhe aceder no script. reactive() envolve um objeto cujas propriedades são reativas sem .value. A diferença prática essencial é que reactive() perde a reatividade quando é desestruturado ou quando o objeto inteiro é reatribuído, enquanto ref() não tem nenhum dos dois problemas. A documentação do Vue e a maioria dos guias da comunidade recomendam ref() por omissão.

Stack relacionado