引子
JavaScript本身是一個弱類型語言,項目中容易發生錯誤,做好網頁錯誤監控,能幫助開發者迅速定位問題,保證線上穩定。
介紹 errorHandler、errorCaptured
文檔傳送門: errorHandler、errorCaptured
errorHandler
指定組件的渲染和觀察期間未捕獲錯誤的處理函數。這個處理函數被調用時,可獲取錯誤信息和 Vue 實例
Vue.config.errorHandler = function (err, vm, info) { #處理錯誤信息, 進行錯誤上報 #err錯誤對象 #vm Vue實例 #`info` 是 Vue 特定的錯誤信息,比如錯誤所在的生命周期鈎子 #只在 2.2.0+ 可用 }
版本分割點
- 2.2.0 起,捕獲組件生命周期鈎子里的錯誤。同樣的,當這個鈎子是 undefined 時,被捕獲的錯誤會通過 console.error 輸出而避免應用崩潰
- 2.4.0 起,也會捕獲 Vue 自定義事件處理函數內部的錯誤
- 2.6.0 起,也會捕獲 v-on DOM 監聽器內部拋出的錯誤。另外,如果任何被覆蓋的鈎子或處理函數返回一個 Promise 鏈 (例如 async 函數),則來自其 Promise 鏈的錯誤也會被處理
errorCaptured
當捕獲一個來自子孫組件的錯誤時被調用。此鈎子會收到三個參數:錯誤對象、發生錯誤的組件實例以及一個包含錯誤來源信息的字符串。此鈎子可以返回 false 以阻止該錯誤繼續向上傳播
錯誤傳播規則
- 默認情況下,如果全局的 config.errorHandler定義,所有的錯誤仍會發送它,因此這些錯誤仍然會向單一的分析服務的地方進行匯報
- 如果一個組件的繼承或父級從屬鏈路中存在多個 errorCaptured 鈎子,則它們將會被相同的錯誤逐個喚起。
- 如果此 errorCaptured 鈎子自身拋出了一個錯誤,則這個新錯誤和原本被捕獲的錯誤都會發送給全局的 config.errorHandler,不能捕獲異步promise內部拋出的錯誤和自身的錯誤
- 一個 errorCaptured 鈎子能夠返回 false 以阻止錯誤繼續向上傳播。本質上是說“這個錯誤已經被搞定了且應該被忽略”。它會阻止其它任何會被這個錯誤喚起的 errorCaptured 鈎子和全局的 config.errorHandler
錯誤信息示例 errorHandler、errorCaptured
1.errorHandler
vue 項目錯誤正常展示
示例代碼如下:
export default { created() { let a = null; if(a.length > 1) { // ... } } };
正常情況下,上述代碼會報錯:
vue 項目錯誤捕獲以及當中的缺陷
繼上面后,我們嘗試通過 Vue.config.errorHander
捕獲:
Vue.config.errorHandler = (err, vm, info) => { console.log('進來啦~'); } export default { created() { let a = null; if(a.length > 1) { // ... } } };
然后控制台就不會對外拋錯:
那么在錯誤監控系統中,理論上我們只去捕獲報錯而不去攔截報錯,那么要怎么做才能把錯誤外拋到控制台呢?
簡單點,就加個console.error(err)
:
Vue.config.errorHandler = (err, vm, info) => { console.log('進來啦~'); console.error(err);~~~~ } export default { created() { let a = null; if(a.length > 1) { // ... } } };
控制台將會得到下面截圖:
那么這樣就可以了,錯誤的上報我們可以再Vue.config.errorHandler
中去做,完了再去把 Vue 中的這個“短板”補上,讓錯誤繼續正常拋出來。那么此時錯誤上報的函數(比如這函數是是captureError()
)應該這么去調用:
Vue.config.errorHandler = (err, vm, info) => { console.log('進來啦~'); // 錯誤上報到收集報錯的平台 captureError(err); } export default { created() { let a = null; if(a.length > 1) { // ... } } };
2.errorCaptured (err, vm, info) => ?Boolean 類似於React 錯誤處理邊界
<error-boundary> <another-component/> </error-boundary>
Vue.component('ErrorBoundary', { data: () => ({ error: null }), errorCaptured (err, vm, info) { this.error = `${err.stack}\n\nfound in ${info} of component` return false }, render (h) { if (this.error) { return h('pre', { style: { color: 'red' }}, this.error) } // ignoring edge cases for the sake of demonstration return this.$slots.default[0] } })
參考https://segmentfault.com/a/1190000018606181、https://segmentfault.com/a/1190000021706923?utm_source=tag-newest