This change will not affect <template>
users.
Here is a quick summary of what has changed:
h
is now globally imported instead of passed to render functions as an argumentFor more information, read on!
In 2.x, the render
function would automatically receive the h
function (which is a conventional alias for createElement
) as an argument:
// Vue 2 Render Function Example export default { render(h) { return h('div') } }
In 3.x, h
is now globally imported instead of being automatically passed as an argument.
// Vue 3 Render Function Example import { h } from 'vue' export default { render() { return h('div') } }
In 2.x, the render
function automatically received arguments such as h
.
// Vue 2 Render Function Example export default { render(h) { return h('div') } }
In 3.x, since the render
function no longer receives any arguments, it will primarily be used inside of the setup()
function. This has the added benefit of gaining access to reactive state and functions declared in scope, as well as the arguments passed to setup()
.
import { h, reactive } from 'vue' export default { setup(props, { slots, attrs, emit }) { const state = reactive({ count: 0 }) function increment() { state.count++ } // return the render function return () => h( 'div', { onClick: increment }, state.count ) } }
For more information on how setup()
works, see our Composition API Guide.
In 2.x, domProps
contained a nested list within the VNode props:
// 2.x { staticClass: 'button', class: {'is-outlined': isOutlined }, staticStyle: { color: '#34495E' }, style: { backgroundColor: buttonColor }, attrs: { id: 'submit' }, domProps: { innerHTML: '' }, on: { click: submitForm }, key: 'submit-button' }
In 3.x, the entire VNode props structure is flattened. Using the example from above, here is what it would look like now.
// 3.x Syntax { class: ['button', { 'is-outlined': isOutlined }], style: [{ color: '#34495E' }, { backgroundColor: buttonColor }], id: 'submit', innerHTML: '', onClick: submitForm, key: 'submit-button' }
In 2.x, when a component has been registered, the render function would work well when passing the component's name as a string to the first argument:
// 2.x Vue.component('button-counter', { data() { return { count: 0 } } template: ` <button @click="count++"> Clicked {{ count }} times. </button> ` }) export default { render(h) { return h('button-counter') } }
In 3.x, with VNodes being context-free, we can no longer use a string ID to implicitly lookup registered components. Instead, we need to use an imported resolveComponent
method:
// 3.x import { h, resolveComponent } from 'vue' export default { setup() { const ButtonCounter = resolveComponent('button-counter') return () => h(ButtonCounter) } }
For more information, see The Render Function Api Change RFC (opens new window).
Migration build flag: RENDER_FUNCTION
h
being globally imported means that any library that contains Vue components will include import { h } from 'vue'
somewhere. As a result, this creates a bit of overhead since it requires library authors to properly configure the externalization of Vue in their build setup:
See Render Function Guide for more detailed documentation!
© 2013–present Yuxi Evan You
Licensed under the MIT License.
https://v3.vuejs.org/guide/migration/render-function-api.html