DEV Community

Cover image for Render functions in Vue
Jakub Andrzejewski
Jakub Andrzejewski

Posted on

6 1 1 1 1

Render functions in Vue

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)
Enter fullscreen mode Exit fullscreen mode
  • tag: A string (e.g. 'div') or a component
  • props: An object of attributes or props
  • children: A string, array, or another h() 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!')
  }
}
Enter fullscreen mode Exit fullscreen mode

Which is equivalent to:

<template>
  <div class="box">Hello from a render function!</div>
</template>
Enter fullscreen mode Exit fullscreen mode

Additionally, we can create render functions with nested children:

render() {
  return h('ul', null, [
    h('li', null, 'Item 1'),
    h('li', null, 'Item 2')
  ])
}
Enter fullscreen mode Exit fullscreen mode

In Render funtions we can use Props and Events:

render() {
  return h('button', {
    onClick: () => alert('Clicked!')
  }, 'Click Me')
}
Enter fullscreen mode Exit fullscreen mode

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)
}
Enter fullscreen mode Exit fullscreen mode

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)
      )
    )
  }
}
Enter fullscreen mode Exit fullscreen mode

Equivalent template version:

<ul>
  <li v-for="item in items" :key="item.id">{{ item.name }}</li>
</ul>
Enter fullscreen mode Exit fullscreen mode

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>
  }
}
Enter fullscreen mode Exit fullscreen mode

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:

Vue School Link

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)

Collapse
 
sawyerwolfe profile image
Sawyer Wolfe

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.

ACI image

ACI.dev: Fully Open-source AI Agent Tool-Use Infra (Composio Alternative)

100% open-source tool-use platform (backend, dev portal, integration library, SDK/MCP) that connects your AI agents to 600+ tools with multi-tenant auth, granular permissions, and access through direct function calling or a unified MCP server.

Check out our GitHub!