While templates are the go-to method for building components in Vue, there are times when you need more flexibility or dynamic control. That’s where render functions come in.
In this article, we'll explore what render functions are, when to use them, and how to write them using both the traditional h()
function and the newer JSX syntax.
Enjoy!
🤔 What are Render functions?
A render function is an alternative to Vue’s template syntax. Instead of using HTML-like templates, you use JavaScript to describe what the DOM should look like.
It gives you full programmatic control over your component's output — ideal for dynamic UIs or reusable low-level components.
Use render functions when:
- You need full control over DOM output
- You want to generate elements dynamically
- You’re writing functional or low-level UI libraries
- You prefer programmatic logic over declarative templates
However, don’t use render functions for everything — Vue’s template syntax is optimized and easier to read in most cases.
🟢 How to use Render functions in Vue?
In Vue 3, the h()
function (short for "hyperscript") is used to create virtual DOM nodes:
h(tag, props, children)
-
tag
: A string (e.g.'div'
) or a component -
props
: An object of attributes or props -
children
: A string, array, or anotherh()
call
The real life example could look like this:
import { h } from 'vue'
export default {
name: 'RenderExample',
render() {
return h('div', { class: 'box' }, 'Hello from a render function!')
}
}
Which is equivalent to:
<template>
<div class="box">Hello from a render function!</div>
</template>
Additionally, we can create render functions with nested children:
render() {
return h('ul', null, [
h('li', null, 'Item 1'),
h('li', null, 'Item 2')
])
}
In Render funtions we can use Props and Events:
render() {
return h('button', {
onClick: () => alert('Clicked!')
}, 'Click Me')
}
You can also use this.$props
, this.$slots
, etc., within the render function to access the component’s reactive context.
And we can also create elements dynamically:
render() {
const tag = this.isHeading ? 'h1' : 'p'
return h(tag, null, this.text)
}
This lets you dynamically choose the HTML tag at runtime — something not as straightforward with template syntax.
We can also render List from Props
export default {
props: ['items'],
render() {
return h('ul', null,
this.items.map(item =>
h('li', { key: item.id }, item.name)
)
)
}
}
Equivalent template version:
<ul>
<li v-for="item in items" :key="item.id">{{ item.name }}</li>
</ul>
And finally, we can use the JSX Alternative (Optional). If you're using a build setup with JSX support (like Vite + Vue plugin), you can write components like this:
export default {
props: ['text'],
setup(props) {
return () => <div class="greeting">{props.text}</div>
}
}
JSX lets you write render functions in a more HTML-like syntax, which is often more readable.
📖 Learn more
If you would like to learn more about Vue, Nuxt, JavaScript or other useful technologies, checkout VueSchool by clicking this link or by clicking the image below:
It covers most important concepts while building modern Vue or Nuxt applications that can help you in your daily work or side projects 😉
✅ Summary
Render functions in Vue offer a powerful way to define component output using JavaScript logic instead of templates. They're not for every use case, but they unlock capabilities that are difficult or verbose in templates — making them a great tool for advanced Vue development.
Take care and see you next time!
And happy coding as always 🖥️
Top comments (1)
Great overview! If anyone is interested in collaborating on a Vue component library using render functions or JSX, let me know—would love to work together on it.