第128题 如何统一监听Vue组件报错

  • window.onerror
    • 全局监听所有JS错误,包括异步错误
    • 但是它是JS级别的,识别不了Vue组件信息,Vue内部的错误还是用Vue来监听
    • 捕捉一些Vue监听不到的错误
  • errorCaptured生命周期
    • 监听所有下级组件 的错误
    • 返回false会阻止向上传播到window.onerror
  • errorHandler配置
    • Vue全局错误监听,所有组件错误都会汇总到这里
    • errorCaptured返回false,不会传播到这里
    • window.onerrorerrorHandler互斥,window.onerror不会在被触发,这里都是全局错误监听了
  • 异步错误
    • 异步回调里的错误,errorHandler监听不到
    • 需要使用window.onerror
  • 总结
    • 实际工作中,三者结合使用
    • promisepromise没有被catch的报错,使用onunhandledrejection监听)和setTimeout异步,vue里面监听不了
        window.addEventListener("unhandledrejection", event => {
      // 捕获 Promise 没有 catch 的错误
      console.info('unhandledrejection----', event)
    })
    Promise.reject('错误信息')
    // .catch(e => console.info(e)) // catch 住了,就不会被 unhandledrejection 捕获
* `errorCaptured`监听一些重要的、有风险组件的错误
* `window.onerror`和`errorCaptured`候补全局监听
    // main.js
    const app = createApp(App)
    
    // 所有组件错误都会汇总到这里
    // window.onerror和errorHandler互斥,window.onerror不会在被触发,这里都是全局错误监听了
    // 阻止向window.onerror传播
    app.config.errorHandler = (error, vm, info) => {
      console.info('errorHandler----', error, vm, info)
    }
    // 在app.vue最上层中监控全局组件
    export default {
      mounted() {
        /**
         * msg:错误的信息
         * source:哪个文件
         * line:行
         * column:列
         * error:错误的对象
         */
        // 可以监听一切js的报错, try...catch 捕获的 error ,无法被 window.onerror 监听到
        window.onerror = function (msg, source, line, column, error) {
          console.info('window.onerror----', msg, source, line, column, error)
        }
        // 用addEventListener跟window.onerror效果一样,参数不一样
        // window.addEventListener('error', event => {
        //   console.info('window error', event)
        // })
      },
      errorCaptured: (errInfo, vm, info) => {
        console.info('errorCaptured----', errInfo, vm, info)
        // 返回false会阻止向上传播到window.onerror
        // 返回false会阻止传播到errorHandler
        // return false
      },
    }
    // ErrorDemo.vue
    export default {
      name: 'ErrorDemo',
      data() {
        return {
          num: 100
        }
      },
      methods: {
        clickHandler() {
          try {
            this.num() // 报错
          } catch (ex) {
            console.error('catch.....', ex)
            // try...catch 捕获的 error ,无法被 window.onerror 监听到
          }
    
          this.num() // 报错
        }
      },
      mounted() {
        // 被errorCaptured捕获
        // throw new Error('mounted 报错')
    
        // 异步报错,errorHandler、errorCaptured监听不到,vue对异步报错监听不了,需要使用window.onerror来做
        // setTimeout(() => {
        //     throw new Error('setTimeout 报错')
        // }, 1000)
      },
    }
Last Updated:
Contributors: leeguooooo