Vue3: Options API vs Composition API (pt/br)
Tags: braziliandevs, frontend, webdev, vue
Published: 2023-09-04 15:01:25

> <small>_[Read it in English](https://dev.to/sucodelarangela/vue3-options-api-vs-composition-api-en-1fbo)_</small>

Até o Vue 2, só tínhamos uma maneira de se criar componentes, sintaticamente falando. Porém, com [a chegada do **Vue 3** em 2020](https://github.com/vuejs/core/releases/tag/v3.0.0), fomos apresentados a uma nova forma de organizar e reutilizar a lógica de um componente Vue, a **Composition API**. Aqui vamos focar nas principais diferenças entre a **Composition API** e a forma mais tradicional do Vue 2, hoje conhecida como **Options API**.

> _**Sumário**
> [Options API: herança do Vue 2](#options-api-herança-do-vue-2)
> [Composition API: a novidade do Vue 3](#composition-api-a-novidade-do-vue-3)
> [Mas, afinal, qual a melhor?](#mas-afinal-qual-a-melhor)_

![Pílulas de Matrix](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bxrecsedq9jrdz6hylu2.gif)

---

## Options API: herança do Vue 2

Quando usamos a sintaxe da **Options API**, precisamos criar toda a lógica de um componente dentro de um <mark>"objeto de opções",</mark> dividido em grupos de propriedades.

Abaixo, listamos as principais opções na estrutura básica da lógica com Options API, apesar de nem todas serem obrigatórias ou necessárias dependendo do objetivo do seu componente:

- **data**: onde definimos nossas propriedades reativas (variáveis e estados). Toda propriedade retornada de `data` fica exposta ao `this` do componente;
- **methods**: onde declaramos funções que alteram estados e disparam atualizações. Métodos podem ser usados como _event handlers_ no template;
- **computed**: onde declaramos métodos _getters_ para tratamento e retorno de dados reativos do nosso componente;
- **Lifecycle Hooks**: que são métodos _built-in_ de ciclo de vida, que executam funções em diferentes [estágios da vida de um componente](https://pt.vuejs.org/guide/essentials/lifecycle.html) (quando ele é montado, atualizado, etc).

Temos também outras opções, como `name`, `components`, `props`, `directives`, `watch` e `emits`, entre outras, mas podemos falar um pouco mais sobre eles em um artigo futuro.

Aqui temos um exemplo simples de Options API, onde declaramos uma propriedade reativa (`valor`), um método que altera `valor` e uma propriedade computada que retorna o dobro de `valor`. Por serem reativas, as alterações são instantaneamente renderizadas na tag `<p>`. Além disso, temos um _lifecycle hook_ que registrará no console uma mensagem sempre que o componente for atualizado.

```vue
<template>
  <p>Valor: {{ valor }}, Dobro: {{ valorEmDobro }}</p>
  <button @click="somaValor">Clique para aumentar o valor</button>
</template>

<script>
export default {
  data() {
    return { valor: 0 }
  },
  computed: {
    valorEmDobro () {
      return this.valor * 2;
    }
  },
  methods: {
    somaValor() {
      this.valor++;
    }
  },
  updated() {
    console.log(`O valor agora é ${this.valor}`);
    console.log(`O valor em dobro agora é ${this.valorEmDobro}`);
  };
};
</script>
```

Em um componente pequeno como nosso exemplo, a Options API parece uma boa alternativa de organização de código, com "cada coisa no seu quadrado". Para quem já vem do desenvolvimento com Vue 2, ela também tem a vantagem da familiaridade ao iniciar um novo projeto ou [migrar um projeto legado para o Vue 3](https://v3-migration.vuejs.org/).

No entanto, em componentes bem maiores, a Options API pode acabar se tornando um problema: os blocos de códigos relacionados entre si acabam ficando muito espalhados dentro do `script` do componente, prejudicando a compreensão da lógica e a manutenibilidade.

Além disso, por ter uma sintaxe voltada para a orientação de objetos, a Options API também tem suporte limitado para o uso com TypeScript, dificultando a vida do desenvolvedor.

---

## Composition API: a novidade do Vue 3

Na **Composition API**, toda a lógica do componente é definida usando <mark>funções importadas da API de Composição</mark> e são, normalmente, utilizadas com a tag `<script setup>`.

O atributo `setup` nos permite utilizar a API de Composição com menos ["boilerplate"](https://pt.wikipedia.org/wiki/Boilerplate_code) e a sua sintaxe dispensa a declaração de opções em blocos, como vimos na Options API.

Abaixo vamos reescrever o componente anterior utilizando a Composition API:

```vue
<template>
  <p>Valor: {{ valor }}, Dobro: {{ valorEmDobro }}</p>
  <button @click="somaValor">Clique para aumentar o valor</button>
</template>

<script setup>
import { ref, computed, onUpdated } from 'vue'

const valor = ref(0);

const somaValor = () => {
  valor.value++;
};

onUpdated(() => console.log(`O valor agora é ${valor.value}`));

const valorEmDobro = computed(() => {
  return valor.value * 2;
});

onUpdated(() => {
  console.log(`O valor em dobro agora é ${valorEmDobro}`)
});
</script>
```

Vamos ver o que a Composition API nos trouxe de diferente?

- Para criar uma propriedade reativa, importamos e utilizamos `ref` (há também o `reactive`, utilizado para objetos);
- Ao mudar o valor da propriedade reativa, usamos `.value`, pois `ref` retorna um objeto;
- Usamos uma função simples (`somaValor`) para alterar o estado sem precisar declará-las dentro de um protótipo como `methods`;
- Criamos uma propriedade computada utilizando `computed()` para retornar o dobro do valor sempre que este for alterado;
- Também importamos o ciclo de vida `onUpdated()`, que executa uma função sempre que o componente for atualizado. Vale ressaltar que, diferente da Options API, onde você usa o mesmo ciclo de vida apenas uma vez, na Composition API um ciclo de vida pode ser chamado N vezes.

Com isso, a Composition API traz a vantagem de importarmos apenas o que necessitamos dentro do componente, em vez de trazer "por baixo dos panos" toda a API (muitas vezes sem necessidade), o que ajuda a tornar a performance do Vue 3 bem melhor que a do Vue 2.

Também temos um código mais declarativo e mais estruturado, permitindo que possamos agrupar código de forma mais lógica, como demonstra a imagem abaixo:

<figure>
![Agrupamento de código](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v2z75iteuzmewnf99ppm.gif)
<figcaption>
Fonte: <a href='https://segmentfault.com/a/1190000040144197/en' target='_blank'>Jansen</a>
</figcaption>
</figure>
>

Além disso, por possuir uma sintaxe bem mais simples, a Composition API é otimizada para uso com TypeScript. Uma outra vantagem é a facilidade de extrair e encapsular lógica, facilitando o reuso e diminuindo a duplicação de código (o que chamamos de [_Composable_](https://vuejs.org/guide/reusability/composables.html#what-is-a-composable)).

No entanto, apesar de ter sido desenvolvida para ser mais simples de implementar, a Composition API pode exigir uma curva maior de aprendizado para quem já está acostumado com a Options API. Além disso, em componentes muito maiores, se a sua lógica não for bem estruturada, pode acabar se tornando mais verbosa desnecessariamente.

---

## Mas, afinal, qual a melhor?

Bom, a realidade é que não há uma resposta simples pra essa pergunta. Ambas as sintaxes são suportadas pelo **Vue 3** e ambas possuem suas vantagens e desvantagens. Então, no fim das contas, definir qual a melhor ou pior acaba se tornando algo bem pessoal.

Mas falando em pessoalidade, no geral, eu prefiro usar a Composition API em meus projetos pessoais, pela otimização com o TypeScript e pela possibilidade de agrupar as lógicas. No entanto, no meu dia-a-dia como desenvolvedora, utilizo a Options API, pela familiaridade de sintaxe com o Vue 2 e por questão de padronização de código entre as _squads_.

Se você, até agora, só utilizou uma das duas formas, experimente! É possível até mesmo usar um mix de ambas as sintaxes, utilizando a função `setup () {}` dentro do objeto de opções da Options API! Te convido à testar na prática e descobrir qual sintaxe mais te agrada!

_Um xero!_