There are very few cases where you should be using a render function instead of regular templates to create components in Vue.js. And the Render Functions API got slimmer in Vue 3. In this article, we’re going to see a few cases where the use of render functions is justified. By the way, if you need an introduction to render functions, make sure you read my previous post on Render Functions.
This article is going to show you some advanced patterns, so strap in and bear with me!
TL;DR: In my opinion, you should only use render functions when you want to intercept the data passed to the component and change it, and only if you cannot do it with regular template functions and props or similar approaches.
So, please, if you can use a template, use it. You and anyone reading the code will thank me later!
Let’s see a few render functions use-cases. And stay until the end to see my favourite one!
# Intercepting HTML attributes
One of the use-cases I’ve found while developing Design Systems based on CSS classes (ahem, Tailwind) is that you want to make certain classes appear alongside other classes in your DS. And if you want to validate that the classes that are passed are consistent with what you expect, you cannot do that with templates, unless you access the DOM or pass classes via props...
Let me show you the principle with a live example:
As you can see, we’re “reading" the classes passed to the component via
attrs, and if the class passed is
red, we make add
blue. When would you want to do such a thing? To enforce consistency or to add your own logic. Imagine you want to have something like this:
- Every time someone passes the
.xclass, you want to make sure
.yclass is also present.
So, this pattern is probably only interesting for components library authors or Design System authors, and I recognise it, it’s an edge-case probably you won’t even encounter.
Note: did you notice how we’re creating components inside
<script setup> and
defineComponent? Also, the second component is returning a function. This way, we can use
useSlots inside of it (instead of
this.slots). And then, by returning a function, it’s treated as a render function.
Unfortunately for us, in Vue 3, the class object is read-only, so you can only add classes and not remove existing ones. But it’s an example of what you can do with render functions. And the same way we have intercepted the
class attribute, you could intercept other HTML attributes.
slots for Accessibility
Again, let’s consider you’re creating you’re own Design System. And you want to provide a11y and usability hints when someone does something funky in the template. For example:
- By spec, the
aelement cannot contain any interactive (clickable) elements.
So, what if we try to warn our library users of an incorrect markup, in development, before they even need to check it?
I can see how this kind of message could be useful in a big Design System that focuses on **accessibility** (and why shouldn’t you, right?).
# Rendering dynamic templates
You’ve probably encountered this problem while developing an app. You receive a string from some Backend or API that contains a template or some HTML that needs to interpolate some data. For example, it’s commonly needed for internationalisation (i18n) or rendering dynamic dashboards.
Note: As you might have thought, it is an alternative API to
Vue.compile. And for any compilation during runtime, you would need to load the Vue “build" that includes the compiler, so bear in mind it produces a heavier JS bundle and you’ll need to add it into your configuration manually.
For this example, I will showcase an example I had up my sleeve, using Vue 2:
As you can see, it could be a replacement for
v-html if you need to transpile during runtime some expressions or if you need to compile at runtime components. For example, the
<router-view> is also a very common case. Notice how in my example I'm not implementing methods/events. I just wanted to showcase the main idea.
Mandatory note: ❗️ Be careful about rendering user inputs (avoid it or sanitize them), as it can lead to an XSS attack.
These are some of the use-cases of render functions. I hope you have seen something new or you have learned something! 😊 Let me know other use cases of render functions you know about!
Also, remember, when possible, use templates instead!