Vue 组件错误统一监听

Vue 中捕获和处理组件错误的几种方式

问题

如何统一监听 Vue 组件报错?

解答

Vue 提供了多种错误捕获机制,可以组合使用实现统一的错误监听。

1. errorHandler - 全局错误处理

// main.js
const app = createApp(App)

app.config.errorHandler = (err, instance, info) => {
  // err: 错误对象
  // instance: 发生错误的组件实例
  // info: 错误来源信息,如 lifecycle hook, event handler 等
  console.error('全局错误:', err)
  console.log('错误组件:', instance)
  console.log('错误信息:', info)
  
  // 上报错误到监控平台
  reportError({
    type: 'vue-error',
    error: err.message,
    stack: err.stack,
    info
  })
}

2. errorCaptured - 组件级错误捕获

<script setup>
import { onErrorCaptured } from 'vue'

// 捕获子组件错误
onErrorCaptured((err, instance, info) => {
  console.error('子组件错误:', err)
  
  // 返回 false 阻止错误继续向上传播
  // 返回 true 或不返回,错误会继续传播到 errorHandler
  return false
})
</script>

3. 捕获异步错误和 Promise 错误

// main.js

// 捕获未处理的 Promise 错误
window.addEventListener('unhandledrejection', (event) => {
  console.error('Promise 错误:', event.reason)
  reportError({
    type: 'promise-error',
    error: event.reason
  })
})

// 捕获其他 JS 错误
window.onerror = (message, source, line, column, error) => {
  console.error('JS 错误:', message)
  reportError({
    type: 'js-error',
    message,
    source,
    line,
    column,
    stack: error?.stack
  })
}

4. 完整的错误监听方案

// errorHandler.js
export function setupErrorHandler(app) {
  // Vue 组件错误
  app.config.errorHandler = (err, instance, info) => {
    handleError({
      type: 'vue',
      error: err,
      info,
      componentName: instance?.$options?.name
    })
  }

  // Vue 警告(开发环境)
  app.config.warnHandler = (msg, instance, trace) => {
    console.warn('Vue 警告:', msg)
  }

  // Promise 错误
  window.addEventListener('unhandledrejection', (e) => {
    handleError({
      type: 'promise',
      error: e.reason
    })
  })

  // JS 运行时错误
  window.onerror = (msg, source, line, col, error) => {
    handleError({
      type: 'js',
      error,
      message: msg,
      position: { source, line, col }
    })
  }
}

function handleError(errorInfo) {
  // 统一处理:打印、上报、展示等
  console.error('[Error]', errorInfo)
  
  // 上报到监控平台
  // sendToServer(errorInfo)
}
// main.js
import { createApp } from 'vue'
import App from './App.vue'
import { setupErrorHandler } from './errorHandler'

const app = createApp(App)
setupErrorHandler(app)
app.mount('#app')

关键点

  • errorHandler 捕获组件渲染和生命周期中的错误
  • errorCaptured 可在父组件捕获子组件错误,返回 false 阻止向上传播
  • window.onerror 捕获未被 Vue 处理的 JS 错误
  • unhandledrejection 捕获未处理的 Promise 错误
  • 生产环境应将错误上报到监控平台(如 Sentry)