Vue 錯誤處理 — onErrorCaptured 鉤子

本文已整理到 ?? blog

如果我的內容幫助到了您,歡迎點個 Star ?????? 鼓勵鼓勵 :) ~~


Vue 實例有一個 onErrorCaptured 鉤子,每當事件處理程序或生命周期鉤子拋出錯誤時,Vue 會調用該鉤子。

例如,下面的代碼將增加一個計數(shù)器,每次單擊按鈕時,組件 test 都會拋出一個錯誤。

<template>
  <span id="count">{{ count }}</span>
  <test></test>
</template>

<script setup>
import { defineComponent, onErrorCaptured, ref } from 'vue'
import test from './test.vue'

const count = ref(0)
defineComponent({
  test
})

onErrorCaptured(err => {
  console.log('Caught error', err.message)
  ++count.value
  return false
})
</script>

test.vue

<template>
  <button @click="notAMethod()">Throw</button>
</template>

onErrorCaptured 只捕獲嵌套組件中的錯誤

一個常見的問題是,當錯誤發(fā)生在注冊 onErrorCaptured 鉤子的同一組件中時,Vue 不會調用 onErrorCaptured。

例如,如果從上述示例中刪除 test 組件,并將按鈕內聯(lián)到頂級 Vue 實例中,Vue 將不會調用 onErrorCaptured

<template>
  <span id="count">{{ count }}</span>
  <button @click="notAMethod">Throw</button>
</template>

<script setup>
import { defineComponent, onErrorCaptured, ref } from 'vue'
import test from './test.vue'

const count = ref(0)
defineComponent({
  test
})

// Vue 不會調這個鉤子,因為錯誤發(fā)生在這個 Vue 實例中,而不是子組件。
onErrorCaptured(err => {
  console.log('Caught error', err.message)
  ++count.value
  return false
})
</script>

異步錯誤

好的一面是,當異步函數(shù)拋出錯誤時,Vue 會調用 errorCapture()。

例如,如果子組件異步拋出錯誤,Vue 仍然會將錯誤冒泡給父組件。

<template>
  <span id="count">{{ count }}</span>
  <test />
</template>

<script setup>
import { defineComponent, onErrorCaptured, ref } from 'vue'
import test from './test.vue'

const count = ref(0)
defineComponent({
  test
})

onErrorCaptured(err => {
  console.log('Caught error', err.message)
  ++count.value
  return false
})
</script>

test.vue

<template>
  <button @click="test">Throw</button>
</template>

<script setup>
// Vue 會將異步錯誤冒泡到父級的 onErrorCaptured(),因此每次單擊該按鈕時,
// Vue 都會調用帶有 err的 errorCaptured() 鉤子。err.message = 'Oops'
const test = async () => {
  await new Promise(resolve => setTimeout(resolve, 50))
  throw new Error('Oops!')
}
</script>

錯誤傳播

在前面的示例中,您可能已經(jīng)注意到 return false。如果 onErrorCaptured() 函數(shù)沒有 return false,則 Vue 會將錯誤冒泡到父組件的 onErrorCaptured()

<template>
  <span id="count">{{ count }}</span>
  <test1 />
</template>

<script setup>
import { defineComponent, onErrorCaptured, ref } from 'vue'
import test1 from './test1.vue'

// 由于 test1 組件的 onErrorCaptured() 沒有 return false,Vue 將冒泡顯示錯誤。
const count = ref(0)
defineComponent({
  test1
})

onErrorCaptured(err => {
  console.log('Caught top-test error', err.message)
  ++count.value
  return false
})
</script>

test1.vue

<template>
  <test2 />
</template>

<script setup>
import { defineComponent, onErrorCaptured, ref } from 'vue'
import test2 from './test2.vue'

defineComponent({
  test2
})

onErrorCaptured(err => {
  console.log('test 1 error', err.message)
})
</script>

test2.vue

<template>
  <button @click="notAMethod()">Throw</button>
</template>
錯誤傳播

另一方面,如果 onErrorCaptured() 方法使用 return false,Vue 將停止該錯誤的傳播:

// test2.vue
onErrorCaptured(err => {
  console.log('test 1 error', err.message)
  return false
})
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

友情鏈接更多精彩內容