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
- Tratamento de erros em três camadas: errorHandler / onErrorCaptured / errorBoundary
- Os 4 recursos principais do Vue DevTools (Árvore de Componentes / Estado / Eventos / Desempenho)
- Análise de desempenho (API de desempenho + DevTools)
- Integração com o Sentry (monitoramento de erros em produção)
- Localização incorreta do mapa de origem
- 5 dicas comuns para depuração
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:
// 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:
- A página ProductList inteira exibe uma tela em branco
- As mensagens de erro aparecem apenas no console
- Os usuários veem uma página em branco, e atualizar a página não resolve o problema
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
<!-- 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:
- O erro foi interceptado e não se propagará
- Exibir uma página de erro intuitiva
- Envio automático de relatórios de erros para o Sentry
- Os usuários podem clicar em “Tentar novamente”
(3) Receita
Após o tratamento de erros:
- Falha com tela branca: 100% → 0
- Localização do erro: console → painel do Sentry
- Experiência do usuário: Falha → Mensagem de aviso amigável
- Observabilidade: Todos os erros são documentados
3. Tratamento de erros em três níveis
(1) Gerenciamento global de erros: app.config.errorHandler
// 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
<!-- 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
// 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
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
// 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
# 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
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
// 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
npm install @sentry/vue @sentry/tracing
(2) Configuração do main.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
// 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
// main.js:Global
app.config.errorHandler = (err, instance, info) => {
console.error('Global:', err, info)
Sentry.captureException(err)
}
<!-- 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>
// 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
// 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')
▶ 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
// 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'))
▶ 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
errorHandlerconsegue detectar erros assíncronos? R: Não. OerrorHandlerdetecta apenas erros síncronos dentro do Vue. Erros assíncronos (Promise /setTimeout) exigem o uso dotry/catchou dowindow.addEventListener('unhandledrejection').
P:
onErrorCapturedprecisa retornarfalse? R: Não, não precisa. Retornarfalseimpede que o erro se propague para cima. Retornartrue(ou não retornar nada) permite que o erro continue se propagando para cima até a variável globalerrorHandler.
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
onErrorCapturedno Vue 3 e no Vue 2? R: No Vue 2, trata-se de um hookerrorCaptured; no Vue 3, trata-se de uma API de composiçãoonErrorCaptured. O Vue 3 também introduz uma nova variável globalapp.config.errorHandler.
📖 Resumo
- Tratamento de erros em três níveis: global (errorHandler) + componente (onErrorCaptured) + assíncrono (try/catch)
- 5 principais fontes de erros: renderização / ciclo de vida / observação / diretivas / eventos
- Painéis do Vue DevTools 4: Componentes / Linha do tempo / Pinia / Rotas
- 5 principais otimizações de desempenho: v-once / v-memo / shallowRef / markRaw / carregamento diferido
- Integração com o Sentry: Captura automática + Acompanhamento de desempenho + Mapas de origem
- 5 principais métricas de desempenho: FCP / LCP / TTI / TBT / CLS
- Elementos indispensáveis para ambientes de produção: ErrorBoundary + Sentry + Source Map
📝 Exercícios
-
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”
-
Problemas avançados (Dificuldade: ⭐⭐)
Implementar um sistema abrangente de tratamento de erros:
- O
errorHandlerglobal gera registros no console - ErrorBoundary no nível do componente
- Erros assíncronos: try/catch
- 5 categorias de fontes de erro
- O
-
Problema de desafio (Dificuldade: ⭐⭐⭐)
Implementar uma depuração e um monitoramento de erros abrangentes, próprios para ambiente de produção:
- Componente ErrorBoundary + 3 locais diferentes
- Integração com o Sentry (ambiente de produção)
- Configuração do mapa de origem
- 5 dicas importantes para depuração no Vue DevTools
- 5 Principais otimizações de desempenho (v-memo / shallowRef / markRaw / carregamento diferido / v-once)
- Monitoramento de 5 métricas-chave de desempenho (integração com o Lighthouse)