Vue.js: Tratamento de Erros

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

O gerenciamento de erros é um recurso essencial para qualquer aplicativo de produção — ele permite identificar rapidamente a causa de uma falha, reduzir a funcionalidade de maneira controlada e notificar os usuários. O Vue 3 oferece gerenciamento de erros em vários níveis: errorHandler (global), onErrorCaptured (local) e o hook errorCaptured (nível de componente).

A depuração e a otimização de desempenho são igualmente importantes — o Vue DevTools é uma ferramenta essencial que permite visualizar a árvore de componentes, o estado, os eventos e os gargalos de desempenho.

1. O que você vai aprender


2. Um incidente de “trava com tela branca” sem “causa identificável”

(1) Problema: Se uma API retornar um erro, a página inteira fica em branco

O sistema de administração da Alice apresentava um bug crítico:

JS
// ProductList.vue
const products = ref([])
onMounted(async () => {
  const res = await fetch('/api/products')
  products.value = await res.json()  // ❌ The backend returns non-JSON → throws error
})

Experiência do usuário:

O gerente de produto Charlie:

“Alice, os clientes estão reclamando de páginas em branco. Precisamos: 1) evitar que a página inteira trave; 2) exibir uma mensagem de erro; 3) registrar o ocorrido em nosso sistema de monitoramento.”

(2) Soluções para os limites de erro do Vue

VUE
<!-- Parent Component:Error Boundary -->
<template>
  <ErrorBoundary>
    <ProductList />
  </ErrorBoundary>
</template>

<!-- ErrorBoundary.vue -->
<script setup>
import { onErrorCaptured, ref } from 'vue'
const error = ref(null)

onErrorCaptured((err, instance, info) => {
  console.error('Caught:', err)
  // 1. Display error message
  error.value = err.message
  // 2. Report to Sentry
  Sentry.captureException(err)
  // 3. Prevent upward transmission
  return false
})
</script>

<template>
  <div v-if="error" class="error">
    <h3>⚠️ Something went wrong</h3>
    <p>{{ error }}</p>
    <button @click="retry">Retry</button>
  </div>
  <slot v-else />
</template>

Experiência do usuário:

(3) Receita

Após o tratamento de erros:


3. Tratamento de erros em três níveis

(1) Gerenciamento global de erros: app.config.errorHandler

JS
// main.js
import { createApp } from 'vue'
import App from './App.vue'

const app = createApp(App)

// ✅ Global Error Handling
app.config.errorHandler = (err, インスタンス, info) => {
  console.エラー('Global エラー:', err)
  console.log('Component:', インスタンス)
  console.log('Info:', info)  // 'render' / 'watch' / 'lifecycle hook'
  
  // Report to Sentry
  Sentry.captureException(err)
  
  // User Notification
  showErrorNotification('Something went wrong')
}

(2) Erro no nível do componente: onErrorCaptured

VUE
<!-- ErrorBoundary.vue -->
<script setup>
import { onErrorCaptured, ref } from 'vue'

const error = ref(null)

// ✅ Catching Child Component Errors
onErrorCaptured((err, instance, info) => {
  console.error('Boundary caught:', err)
  error.value = {
    message: err.message,
    stack: err.stack,
    info
  }
  
  // Prevent upward transmission
  return false
})
</script>

<template>
  <div v-if="error" class="error-boundary">
    <h3>⚠️ {{ error.message }}</h3>
    <details>
      <summary>Stack trace</summary>
      <pre>{{ error.stack }}</pre>
    </details>
    <button @click="reset">Retry</button>
  </div>
  <slot v-else />
</template>

(3) Comparação dos níveis de erro

Nível API Escopo Aplicável a
Global app.config.errorHandler Todos os erros não capturados Obrigatório para produção
Componente onErrorCaptured Erro no componente filho Limite de erro local
Assíncrono try/catch / window.onunhandledrejection Erro de Promise Tratamento manual

(4) As 5 principais fontes de erros

JS
// 1. Rendering Error(Template syntax error)
app.config.errorHandler = (err, instance, info) => {
  if (info === 'render') console.error('Render error:', err)
}

// 2. Lifecycle Hook Error
if (info === 'mounted') console.error('Mounted error:', err)

// 3. watch Callback Error
if (info === 'watcher callback') console.error('Watch error:', err)

// 4. Custom Command Error
if (info === 'directive') console.error('Directive error:', err)

// 5. Error Handling
if (info === 'v-on handler') console.error('Event error:', err)

4. Visualização do DevTools

(1) 4 painéis principais

Painel Função Finalidade
Componentes Árvore de componentes, estado, props, emissões Compreender a estrutura dos componentes, dados de depuração
Linha do tempo Eventos, ciclo de vida, desempenho Acompanhar fluxos de eventos e gargalos de desempenho
Pinia/Vuex Armazenamento de estado Depuração do estado global
Rotas Histórico de rotas Depuração de redirecionamentos de rotas

(2) Como usar o Painel de Componentes

TEXT 📖 Somente leitura
1. Open DevTools(F12 / Cmd+Opt+I)
2. Switch to Vue Tags
3. Click a component in the component tree
4. Display on the right:
   - State(Responsive Data)
   - Props
   - Emits
   - Slots
   - Lifecycle

(3) As 5 principais dicas sobre o DevTools

JS
// 1. Real-time editing state(Development Mode)
// DevTools Edit directly in the document,Watch the component respond in real time

// 2. Time Travel(Pinia)
// Switch to Pinia Panel → Base → You can replay each step state Changes

// 3. Performance Labels
// import { markRaw } from 'vue'
// Big Data Objects Used For markRaw Mark,DevTools Does not perform a deep traversal

// 4. Components highlight
// DevTools → top right corner"Eyes"Icon → Highlight Components on Mouse Hover

// 5. Route Redirection
// DevTools → Routing Tags → Look at each redirect path + params

(4) Instalar o Vue DevTools

BASH
# Chrome Extensions
# https://chromewebstore.google.com/detail/vuejs-devtools/odjccnclnlddjlajjphfdmhnlhaglgki

# Firefox Extensions
# https://addons.mozilla.org/en-US/firefox/addon/vue-js-devtools/

# or a standalone app(Recommendations)
# https://devtools.vuejs.org/

5. Análise de desempenho

(1) API de Desempenho da View 3

JS
import { onMounted, onUnmounted } from 'vue'

onMounted(() => {
  performance.mark('app-start')
  
  // Your code
  loadData()
  
  performance.mark('app-end')
  performance.measure('app-load', 'app-start', 'app-end')
  
  const measure = performance.getEntriesByName('app-load')[0]
  console.log(`App loaded in ${measure.duration}ms`)
})

(2) 5 dicas importantes para otimizar o desempenho

JS
// 1. v-once:Render only once
<h1 v-once>{{ タイトル }}</h1>

// 2. v-memo:Cache Subtree
<div v-memo="[item.id, item.updatedAt]">
  <!-- Only re-render on id or updatedAt changes -->
</div>

// 3. shallowRef:Big Data Does Not Respond Deeply
const bigList = shallowRef([...10000 アイテム])

// 4. markRaw:Third-party ライブラリ is not responding
const map = markRaw(new Map())

// 5. Lazy Loading:Routing / Components
const Heavy = defineAsyncComponent(() => import('./Heavy.vue'))

(3) 5 Indicadores-chave de desempenho

Indicador Meta Método de medição
FCP (First Contentful Paint) < 1,8 s Lighthouse
LCP (Largest Contentful Paint) < 2,5 s Lighthouse
TTI (Tempo até a interação) < 3,8 s Lighthouse
TBT (Tempo Total de Bloqueio) < 200 ms Lighthouse
CLS (Deslocamento de layout) < 0,1 Lighthouse

6. Integração com o Sentry

(1) Instalação

BASH
npm install @sentry/vue @sentry/tracing

(2) Configuração do main.js

JS
import { createApp } from 'vue'
import * as Sentry from '@sentry/vue'
import { Integrations } from '@sentry/tracing'
import App from './App.vue'

// 1. Initialization Sentry
Sentry.init({
  app,
  dsn: 'https://your-dsn@sentry.io/123',
  integrations: [
    new Integrations.BrowserTracing()
  ],
  tracesSampleRate: 1.0,
  // Reduce Sampling in the Production Environment
  // tracesSampleRate: process.env.NODE_ENV === 'production' ? 0.1 : 1.0
  
  // Vue Specific Placement
  logErrors: true,
  release: '1.0.0',
  environment: process.env.NODE_ENV
})

const app = createApp(App)

// 2. Global Error Reporting
app.config.errorHandler = (err, instance, info) => {
  Sentry.captureException(err, {
    extra: {
      component: instance?.$options.name,
      info
    }
  })
}

(3) Configuração do mapa de origem

JS
// vite.config.js
export default {
  ビルド: {
    sourcemap: true  // Generated in the production environment as well source map
  }
}

// Sentry Upload source map
// @sentry/cli releases -o your-org -p your-project files upload-sourcemaps ./dist

(4) 5 Principais Recursos do Sentry

Recurso Finalidade
Monitoramento de erros Captura automaticamente todos os erros; visualize-os no painel
Rastreamento de desempenho Identificação de solicitações lentas e consultas lentas ao banco de dados
Reprodução da sessão Grave as ações do usuário para identificar onde ocorreu o erro
Comunicados sobre Saúde Comparação das taxas de erro por comunicado
Alerta Notificação pelo Slack / e-mail

7. Exemplo completo: 5 técnicas essenciais de depuração

▶ Exemplo: 1. Tratamento de erros em três níveis

JS
// main.js:Global
app.config.errorHandler = (err, instance, info) => {
  console.error('Global:', err, info)
  Sentry.captureException(err)
}
▶ Experimente
VUE
<!-- ErrorBoundary.vue:Components -->
<script setup>
import { onErrorCaptured, ref } from 'vue'
const error = ref(null)
onErrorCaptured((err, instance, info) => {
  error.value = err.message
  return false
})
</script>
JS
// Asynchronous:Manual try/catch
try {
  await fetch('/api/data')
} catch (err) {
  console.error('Async:', err)
  Sentry.captureException(err)
}

▶ Exemplo: 2. As 5 principais fontes de erros

JS
// 1. Rendering Error
if (info === 'render') console.error('Render')

// 2. Life Cycle Errors
if (info === 'mounted') console.error('Mounted')

// 3. watch Error
if (info === 'watcher callback') console.error('Watch')

// 4. Command error
if (info === 'directive') console.error('Directive')

// 5. Event Error
if (info === 'v-on handler') console.error('Event')
▶ Experimente

▶ Exemplo: 3. Visualização do DevTools: 4 painéis

Painel Objetivo
Componentes Árvore de componentes + Estado + Props
Linha do tempo Fluxo de eventos + Ciclo de vida
Pinia Status da loja
Rotas Histórico de rotas

▶ Exemplo: 4. 5 Principais otimizações de desempenho

JS
// 1. v-once
<h1 v-once>{{ title }}</h1>

// 2. v-memo
<div v-memo="[item.id]">...</div>

// 3. shallowRef
const list = shallowRef([...])

// 4. markRaw
const map = markRaw(new Map())

// 5. Lazy Loading
const Heavy = defineAsyncComponent(() => import('./Heavy.vue'))
▶ Experimente

▶ Exemplo: 5. Referência rápida para 5 erros comuns

Erro Sintoma Solução
Falha com tela branca Um erro em um componente faz com que tudo pare de funcionar Envolver com ErrorBoundary
Erro capturado O componente filho falha sem aviso Não se esqueça de retornar false em onErrorCaptured
Falta o mapa de origem Não foi possível localizar o erro de produção vite build sourcemap: true
Baixo desempenho Apresenta lentidão ao listar 1.000 itens v-memo + shallowRef
Vazamento de memória Temporizador continua em execução após a destruição do componente Limpeza no método onUnmounted

▶ Exemplo: 6. 5 Principais cenários de depuração

Cenário Ferramenta
Erro de estado do componente Vue DevTools → Estado
Evento não acionado Vue DevTools → Linha do tempo
Erro de redirecionamento de roteamento DevTools → Roteamento
Falha no ambiente de produção Painel do Sentry
Desempenho lento Desempenho do Lighthouse + DevTools

❓ Perguntas Frequentes

P: O errorHandler consegue detectar erros assíncronos? R: Não. O errorHandler detecta apenas erros síncronos dentro do Vue. Erros assíncronos (Promise / setTimeout) exigem o uso do try/catch ou do window.addEventListener('unhandledrejection').

P: onErrorCaptured precisa retornar false? R: Não, não precisa. Retornar false impede que o erro se propague para cima. Retornar true (ou não retornar nada) permite que o erro continue se propagando para cima até a variável global errorHandler.

P: O Vue DevTools pode ser usado em um ambiente de produção? R: Sim. A compilação de produção habilita automaticamente o DevTools (sem afetar o desempenho). No entanto, recomenda-se desativá-lo no ambiente de produção usando Vue.config.devtools = false (para evitar a exposição da estrutura interna).

P: Como funciona a estrutura de preços do Sentry? R: O plano gratuito inclui 5.000 eventos e 10.000 transações de desempenho por mês. Isso é suficiente para projetos de médio porte. O uso além desses limites é cobrado no modelo de pagamento conforme o uso.

P: Como o v-memo e o v-for funcionam juntos? R: <div v-for="item in items" :key="item.id" v-memo="[item.id, item.updatedAt]">, esse div só é renderizado novamente quando o id ou o updatedAt são alterados.

P: Como faço para depurar um aplicativo SSR? R: Use o depurador do VS Code + o modo de inspeção do Node.js. Como alternativa, use o Sentry para capturar erros do lado do servidor. Ou use a ferramenta de depuração Nitro no Nuxt 3.

P: Qual é a diferença entre onErrorCaptured no Vue 3 e no Vue 2? R: No Vue 2, trata-se de um hook errorCaptured; no Vue 3, trata-se de uma API de composição onErrorCaptured. O Vue 3 também introduz uma nova variável global app.config.errorHandler.


📖 Resumo


📝 Exercícios

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

    Implementar um componente ErrorBoundary:

    • onErrorCaptured: Captura erros dos componentes filhos
    • Exibir uma página de erro de fácil navegação
    • Incluir um botão “Tentar novamente”
  2. Problemas avançados (Dificuldade: ⭐⭐)

    Implementar um sistema abrangente de tratamento de erros:

    • O errorHandler global gera registros no console
    • ErrorBoundary no nível do componente
    • Erros assíncronos: try/catch
    • 5 categorias de fontes de erro
  3. Problema de desafio (Dificuldade: ⭐⭐⭐)

    Implementar uma depuração e um monitoramento de erros abrangentes, próprios para ambiente de produção:

    1. Componente ErrorBoundary + 3 locais diferentes
    2. Integração com o Sentry (ambiente de produção)
    3. Configuração do mapa de origem
    4. 5 dicas importantes para depuração no Vue DevTools
    5. 5 Principais otimizações de desempenho (v-memo / shallowRef / markRaw / carregamento diferido / v-once)
    6. Monitoramento de 5 métricas-chave de desempenho (integração com o Lighthouse)
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%