Skip to content

Commit 1861ee9

Browse files
committed
feat: renderError
1 parent a1d5b22 commit 1861ee9

File tree

4 files changed

+42
-4
lines changed

4 files changed

+42
-4
lines changed

flow/options.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@ declare type ComponentOptions = {
3333
// DOM
3434
el?: string | Element;
3535
template?: string;
36-
render: () => VNode;
36+
render: (h: () => VNode) => VNode;
37+
renderError?: (h: () => VNode, err: Error) => VNode;
3738
staticRenderFns?: Array<() => VNode>;
3839
// lifecycle
3940
beforeCreate?: Function;

src/core/instance/render.js

+9-2
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,15 @@ export function renderMixin (Vue: Class<Component>) {
7878
vnode = render.call(vm._renderProxy, vm.$createElement)
7979
} catch (e) {
8080
handleError(e, vm, `render function`)
81-
// return previous vnode to prevent render error causing blank component
82-
vnode = vm._vnode
81+
// return error render result,
82+
// or previous vnode to prevent render error causing blank component
83+
if (process.env.NODE_ENV !== 'production') {
84+
vnode = vm.$options.renderError
85+
? vm.$options.renderError.call(vm._renderProxy, vm.$createElement, e)
86+
: vm._vnode
87+
} else {
88+
vnode = vm._vnode
89+
}
8390
}
8491
// return empty vnode in case the render function errored out
8592
if (!(vnode instanceof VNode)) {

test/unit/features/error-handling.spec.js

+3-1
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,9 @@ describe('Error handling', () => {
9696
expect(args[1]).toBe(vm.$refs.child) // vm
9797
expect(args[2]).toContain('render function') // description
9898

99-
assertRootInstanceActive(vm).then(done)
99+
assertRootInstanceActive(vm).then(() => {
100+
Vue.config.errorHandler = null
101+
}).then(done)
100102
})
101103
})
102104

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import Vue from 'vue'
2+
3+
describe('Options renderError', () => {
4+
it('should be used on render errors', done => {
5+
Vue.config.errorHandler = () => {}
6+
const vm = new Vue({
7+
data: {
8+
ok: true
9+
},
10+
render (h) {
11+
if (this.ok) {
12+
return h('div', 'ok')
13+
} else {
14+
throw new Error('no')
15+
}
16+
},
17+
renderError (h, err) {
18+
return h('div', err.toString())
19+
}
20+
}).$mount()
21+
expect(vm.$el.textContent).toBe('ok')
22+
vm.ok = false
23+
waitForUpdate(() => {
24+
expect(vm.$el.textContent).toBe('Error: no')
25+
Vue.config.errorHandler = null
26+
}).then(done)
27+
})
28+
})

0 commit comments

Comments
 (0)