本文已整理到 ?? 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
})