0
点赞
收藏
分享

微信扫一扫

Vue 错误处理 — onErrorCaptured 钩子

本文已整理到 👉 ​​blog​​。


Vue 实例有一个 ​​onErrorCaptured​​,每当事件处理程序或生命周期钩子抛出错误时,Vue 会调用该钩子。

例如,下面的代码将增加一个计数器,每次单击按钮时,组件 ​​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​​ 只捕获嵌套组件中的错误

一个常见的问题是,当错误发生在注册 ​​onErrorCaptured​​​ 钩子的同一组件中时,Vue 不会调用 ​​onErrorCaptured​​。

例如,如果从上述示例中删除 ​​test​​​ 组件,并将按钮内联到顶级 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 不会调这个钩子,因为错误发生在这个 Vue 实例中,而不是子组件。
onErrorCaptured(err => {
console.log('Caught error', err.message)
++count.value
return false
})
</script>

异步错误

好的一面是,当异步函数抛出错误时,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>

错误传播

在前面的示例中,您可能已经注意到 ​​return false​​​。如果 ​​onErrorCaptured()​​​ 函数没有 ​​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>

Vue 错误处理 — onErrorCaptured 钩子_事件处理

错误传播

另一方面,如果 ​​onErrorCaptured()​​​ 方法使用 ​​return false​​,Vue 将停止该错误的传播:

// test2.vue
onErrorCaptured(err => {
console.log('test 1 error', err.message)
return false
})

举报

相关推荐

0 条评论