Vue.js: Propriedades Computadas

Última atualização: 2026-08-26

As propriedades computadas (computed) são propriedades especiais do Vue 3 que são recalculadas automaticamente com base em dados reativos. Seu principal valor está no armazenamento em cache — elas só são recalculadas quando os dados dependentes mudam; caso contrário, simplesmente retornam o valor anterior. Compreender as propriedades computadas é fundamental para escrever aplicativos Vue de alto desempenho.

No cerne das propriedades computadas estão três características fundamentais: rastreamento automático de dependências + armazenamento em cache dos resultados + reatividade. Esta aula vai ajudá-lo a dominar seus cinco casos de uso e a evitar suas três armadilhas.

1. O que você vai aprender


2. Um problema de desempenho relacionado ao preço total do carrinho de compras

(1) Problema: 100 produtos são recalculados a cada clique

Alice criou o cálculo do total do carrinho no painel de administração do seu site de comércio eletrônico:

JS
// ❌ The "Broken" Version: Use methods
function cartTotal(items) {
  console.log('Calculating...')  // Print on every call
  return items.reduce((sum, item) => sum + item.price * item.quantity, 0)
}
HTML
<template>
  <div>
    <p>Total: ${{ cartTotal(items) }}</p>
    <p>Tax: ${{ cartTotal(items) * 0.08 }}</p>
    <p>Grand Total: ${{ cartTotal(items) * 1.08 }}</p>
    <button @click="showDate = new Date()">Update Time</button>
  </div>
</template>

O desempenho é péssimo:

A ferramenta de monitoramento de desempenho mostra:

“A função cartTotal é chamada 5.000 vezes a cada carregamento da página. 100 itens × 5.000 = 500.000 cálculos item por item. Aplacação de 3 segundos.”

(2) Solução com computados do Vue: Armazenamento em cache + rastreamento de dependências

JS
import { ref, computed } from 'vue'

const items = ref([
  { price: 100, quantity: 2 },
  { price: 50, quantity: 1 }
])

// ✅ computed:Rely solely on items,items If it hasn't changed, don't recalculate it.
const cartTotal = computed(() => {
  console.log('Calculating...')  // Only at items Print when changes occur
  return items.value.reduce((sum, item) => sum + item.price * item.quantity, 0)
})

// computed Auto-Processing 3 For use in: Count only 1 time
const tax = computed(() => cartTotal.value * 0.08)
const grandTotal = computed(() => cartTotal.value * 1.08)

(3) Receita

Após mudar para “computed”:


3. Uso básico da função computed()

(1) Sintaxe padrão

JS
import { ref, computed } from 'vue'

const count = ref(0)

// Basic Computational Properties
const doubleCount = computed(() => {
  return count.value * 2
})

// Abbreviation
const doubleCount = computed(() => count.value * 2)

// Usage
console.log(doubleCount.value)  // 0
count.value = 5
console.log(doubleCount.value)  // 10

(2) Uso em modelos

VUE
<template>
  <div>
    <p>Count: {{ count }}</p>
    <p>Double: {{ doubleCount }}</p>
    <button @click="count++">+1</button>
  </div>
</template>

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

const count = ref(0)
const doubleCount = computed(() => count.value * 2)
</script>

No modelo, {{ doubleCount }} não é obrigatório .value (descompactado automaticamente).

(3) 5 Principais Características

100%
graph TB
    subgraph ComputedKey Features
        A[Automatic Dependency Tracking]
        B[Cache Results]
        C[Responsive]
        D[Lazy Evaluation]
        E[Chainable calls]
    end
    
    style A fill:#42b883,color:#fff
    style B fill:#42b883,color:#fff
    style C fill:#42b883,color:#fff
    style D fill:#42b883,color:#fff
    style E fill:#42b883,color:#fff
Recurso Descrição
Rastreamento automático de dependências Detecta automaticamente os dados reativos utilizados no corpo das funções
Resultados em cache Acessos múltiplos contam como apenas 1 quando as dependências permanecem inalteradas
Responsivo Recalcula automaticamente quando as dependências mudam
Avaliação preguiçosa Não é avaliada a menos que seja acessada (economiza desempenho)
Encadeável o valor da propriedade computada pode depender de outras propriedades computadas

4. Computed vs. métodos: 5 diferenças principais

Aspecto calculado métodos
Armazenamento em cache ✅ Não há recálculo se as dependências permanecerem inalteradas ❌ Recalcula a cada chamada
Responsivo ✅ Rastreia dependências automaticamente ❌ Não rastreia (requer a passagem manual de parâmetros)
Acesso ao modelo {{ doubleCount }} {{ doubleCount() }}
Parâmetros ❌ Não suportado ✅ Aceita qualquer parâmetro
Casos de uso Valores derivados simples Lógica complexa, tratamento de eventos

(4) 5 cenários à sua escolha

Cenário Usando valores calculados Usando métodos
Duplique o número exibido
Calcular o valor total do carrinho
Processar clique no botão
Enviar solicitação de API
Formatação de data (sem dependências)
Lista de filtros (depende dos dados)
Validação do formulário

5. Getter/Setter: Propriedades calculadas bidirecionais

(1) Por padrão, existe apenas um getter

JS
const firstName = ref('Alice')
const lastName = ref('Smith')

// There is only one getter
const fullName = computed(() => `${firstName.value} ${lastName.value}`)

console.log(fullName.value)  // Alice Smith
// fullName.value = 'Bob Lee'  // ❌ Warning:Calculated properties are read-only.

(2) Getters e setters completos

JS
const firstName = ref('Alice')
const lastName = ref('Smith')

const fullName = computed({
  // Read:Put it together
  get() {
    return `${firstName.value} ${lastName.value}`
  },
  // Write:Unpack
  set(newValue) {
    const parts = newValue.split(' ')
    firstName.value = parts[0]
    lastName.value = parts[1] || ''
  }
})

// ✅ Read and write access is now available
fullName.value = 'Bob Lee'
console.log(firstName.value)  // Bob
console.log(lastName.value)   // Lee

(3) Vinculação bidirecional em modelos

VUE
<template>
  <div>
    <input v-model="fullName">
    <p>First: {{ firstName }}</p>
    <p>Last: {{ lastName }}</p>
  </div>
</template>

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

const firstName = ref('Alice')
const lastName = ref('Smith')

const fullName = computed({
  get: () => `${firstName.value} ${lastName.value}`,
  set: (val) => {
    const parts = val.split(' ')
    firstName.value = parts[0]
    lastName.value = parts[1] || ''
  }
})
</script>

6. Chamadas encadeadas para propriedades calculadas

(1) Cálculos aninhados

JS
const items = ref([
  { price: 100, quantity: 2 },
  { price: 50, quantity: 3 }
])

// First Floor:Total Original Price
const subtotal = computed(() =>
  items.value.reduce((sum, item) => sum + item.price * item.quantity, 0)
)

// Second Floor: Tax (Based on subtotal)
const tax = computed(() => subtotal.value * 0.08)

// Third Floor: Discount (Based on subtotal)
const discount = computed(() => subtotal.value > 200 ? 20 : 0)

// Fourth Floor:Final Total Price
const total = computed(() => subtotal.value + tax.value - discount.value)

console.log(total.value)  // 350 * 1.08 - 20 = 358

(2) Mecanismo de cache com cálculo em cadeia

100%
graph TB
    A[items change] --> B[subtotal Recalculate]
    B --> C[tax Recalculate]
    B --> D[discount Recalculate]
    C --> E[total Recalculate]
    D --> E
    
    style A fill:#42b883
    style B fill:#42b883
    style E fill:#42b883

Apenas os valores calculados que dependem da cadeia serão recalculados; os que não forem utilizados não serão recalculados.


7. Exemplo completo: Preço total de um carrinho de compras em um site de comércio eletrônico

▶ Exemplo: 1. Cálculo básico

VUE
<template>
  <div>
    <p>Subtotal: ${{ subtotal }}</p>
    <p>Tax (8%): ${{ tax }}</p>
    <p>Discount: -${{ discount }}</p>
    <p><strong>Total: ${{ total }}</strong></p>
  </div>
</template>

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

const items = ref([
  { name: 'iPhone', price: 999, quantity: 1 },
  { name: 'Case', price: 50, quantity: 2 }
])

const subtotal = computed(() =>
  items.value.reduce((sum, item) => sum + item.price * item.quantity, 0)
)

const tax = computed(() => subtotal.value * 0.08)
const discount = computed(() => subtotal.value > 1000 ? 50 : 0)
const total = computed(() => subtotal.value + tax.value - discount.value)
</script>
▶ Experimente

▶ Exemplo: 2. getters + setters

VUE
<template>
  <div>
    <input v-model="fullName" placeholder="First Last">
    <p>First: {{ firstName }}</p>
    <p>Last: {{ lastName }}</p>
  </div>
</template>

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

const firstName = ref('Alice')
const lastName = ref('Smith')

const fullName = computed({
  get: () => `${firstName.value} ${lastName.value}`,
  set: (val) => {
    const parts = val.split(' ')
    firstName.value = parts[0] || ''
    lastName.value = parts[1] || ''
  }
})
</script>
▶ Experimente

▶ Exemplo: 3. Chamadas em cadeia calculadas

JS
import { ref, computed } from 'vue'

const score = ref(85)

// First Floor:Base Score
const baseScore = computed(() => score.value)

// Second Floor:Bonus Points(Base Score × Difficulty Level)
const difficultyBonus = computed(() => {
  if (baseScore.value >= 90) return 10
  if (baseScore.value >= 80) return 5
  return 0
})

// Third Floor:Level
const grade = computed(() => {
  const total = baseScore.value + difficultyBonus.value
  if (total >= 95) return 'A+'
  if (total >= 90) return 'A'
  if (total >= 80) return 'B'
  return 'C'
})
▶ Experimente

▶ Exemplo: 4. Comparação entre computados e métodos

JS
// ❌ methods:Recalculate on every call
function getTotal() {
  console.log('Calculated!')  // If used multiple times in the template, it will be printed multiple times.
  return items.value.reduce((sum, i) => sum + i.price * i.quantity, 0)
}

// ✅ computed: Count only 1 time
const total = computed(() => {
  console.log('Calculated!')  // Print Only 1 time
  return items.value.reduce((sum, i) => sum + i.price * i.quantity, 0)
})
▶ Experimente

▶ Exemplo: 5. Cinco cenários de comparação de desempenho

Cena Número de métodos chamados Número de chamadas calculadas
Usado 1 vez no modelo 1 1
Usado 3 vezes no modelo 3 1
Usado 10 vezes no modelo 10 1
O componente pai é atualizado, mas os itens permanecem inalterados Recuperado Não recalculado
Alterações nas dependências Revogação Recálculo

▶ Exemplo: 6. 5 erros comuns

Erro Sintoma Solução
Substituir métodos por expressões calculadas Baixo desempenho com uso repetido Mudar para expressões calculadas
Passagem incorreta de parâmetros para computed Erro computed não aceita parâmetros; use methods em vez disso
setter: Escreva o seu próprio Loop infinito setter: Modifique a dependência; não use fullName.value = ...
Dependência circular A→B→A Loop infinito Remova uma das dependências
Lógica complexa escrita em propriedades calculadas Difícil de depurar Extraia para um método; faça com que a propriedade calculada chame o método

❓ Perguntas Frequentes

P: O que devo usar — computed ou methods? R: Use computed sempre que possível (armazenamento em cache + rastreamento automático). Use methods apenas nas seguintes situações: (1) quando precisar passar parâmetros; (2) quando não depender de dados reativos; (3) para manipuladores de eventos (@click, etc.).

P: O computed pode aceitar parâmetros? R: Não. O computed só pode ter 0 parâmetros. Se você precisar passar parâmetros, use o methods em vez disso: getDouble(n) { return n * 2 }, ou faça com que o computed retorne uma função: computed(() => (n) => n * 2).

P: É possível acessar computed fora de setup? R: Sim. computed retorna um objeto ref, que pode ser passado para outros componentes ou funções. No entanto, para manter a reatividade, recomenda-se usar computed como uma “referência derivada”.

P: Qual é a diferença entre computed e watch? R: computed é um “valor derivado” (cálculo de um novo valor com base em dados), enquanto watch é um “observador” (execução de efeitos colaterais quando os dados mudam). computed é adequado para cálculos puros, enquanto watch é adequado para fazer solicitações, definir estado e assim por diante.

P: Por que o computed tem melhor desempenho do que o methods? R: Armazenamento em cache. O methods executa a função a cada chamada, enquanto o computed só é executado quando suas dependências mudam. No modelo, usar o computed três vezes resulta em apenas um cálculo; usar o methods resulta em três cálculos.

P: Como faço para escrever um setter de forma que ele não entre em um loop infinito? R: No setter, atualize apenas as dependências do computed (ref); não atribua um valor diretamente ao próprio computed. Por exemplo, o setter para fullName deve atualizar firstName e lastName, e não fullName.value = ....

P: O computed pode ser assíncrono? R: Não. O computed é síncrono; use watch ou watchEffect para operações assíncronas. Se você precisar de “propriedades calculadas assíncronas”, use a combinação de data() { return { result: null } } e watch + onMounted.


📖 Resumo


📝 Exercícios

  1. Questões básicas (Dificuldade: ⭐)

    Escreva uma propriedade computada wordCount que conte o número de palavras em um trecho de texto (usando split para dividir o texto por espaços).

    Dados: const text = ref('Hello Vue 3 from Alice') Deveria exibir 4.

  2. Problemas avançados (Dificuldade: ⭐⭐)

    Escreva um cálculo do total do carrinho de compras que inclua três propriedades calculadas:

    • subtotal: A soma do preço e da quantidade de todos os itens
    • discount: Economize 10 em pedidos de 100 ou mais; economize 30 em pedidos de 200 ou mais
    • total: subtotal - desconto
    • 3 itens: iPhone $999 × 1, capa $50 × 2, carregador $30 × 1
  3. Problema de desafio (Dificuldade: ⭐⭐⭐)

    Implementar um “sistema completo de cálculo do total do carrinho de compras”:

    1. 5 produtos, cada um com nome, preço e quantidade
    2. subtotal / imposto (8%) / desconto (20 de desconto para compras de 200 ou mais) / total — 4 valores calculados
    3. Use getters e setters para a propriedade calculada fullName; no setter, atualize firstName e lastName com base na entrada.
    4. Testar o rastreamento de dependências para 5 propriedades calculadas (quais são recalculadas após a modificação de qualquer produto)
    5. Use o Mermaid para desenhar um gráfico de dependências para propriedades calculadas
Web-Tutorial.com

Equipe Técnica Web-Tutorial

Uma plataforma de tutoriais mantida por diversos desenvolvedores. Cada tutorial é escrito e revisado por profissionais da área correspondente. Trabalhamos para manter nosso conteúdo preciso e confiável — se encontrar algum problema, avise-nos.

100%