There are multiple ways to render a functional component in Vue.js. Depending on the use case and on your own taste you may prefer one over another, which is a great thing from a framework that you can adapt to your preferences.
In Functional Components in Vue.js you’ve seen how to create a FunctionalButton component using a render function. That’s ok for a simple example, but for more sophisticated ones it can be a pain.
Let’s see which other options you have by taking that FunctionalButton example. Keep in mind that under the hood, they all compile to a render function.
This option is available since Vue version 2.5.0, and probably is one of the most popular, given that templates are the default way in Vue, so you are probably familiar with it.
Let’s create a FunctionalButtonTemplate.vue file with the following content:
<template functional>
<button :disabled="props.disabled" @click="listeners.click">
<slot />
</button>
</template>
As you can see, you have direct access to the context object by accessing its properties, such as props
or listeners
. The children
property is just the default slot, as usual for templates.
The only downside of this approach is that is not possible to create a higher order component or do prop manipulation, since using a template is more limited than plain JavaScript (or JSX, which is JavaScript too).
JSX is just a much nicer way to write render functions, transpiled using babel-plugin-transform-vue-jsx. It’s the de-facto way to write components in React and is just as valid in Vue.
Let’s create the JSX version of the FunctionalButton component:
export default {
functional: true,
render: (h, { data, children }) =>
<button {...data}>
{children}
</button >
};
The main advantage is that you have the full power of a render function and JavaScript, with a HTML-like syntax. That’s why you can easily proxy props by writing {...data}
.
When React users see the previous JSX example, they probably say Why you need that functional: true
thing?. Well that’s a valid statement, since they just need to export a plain function, that’s all.
By the time of writing, you can do it in Vue by using babel-plugin-jsx-vue-functional. All you need to do is install it:
$ npm install --save-dev babel-plugin-jsx-vue-functional
Then add it to the .babelrc config:
{
"presets": ["es2015"],
"plugins": ["jsx-vue-functional", "transform-vue-jsx"]
}
And finally, you’d be able to write the previous example by just exporting a named arrow function:
export const FunctionalButton = ({ data, children }) =>
<button {...data}>
{children}
</button >
As you can see, one of Vue’s main advantages is to be approachable by allowing to write a component in several ways, making it a framework that adapts to different people and teams.
Find the code of this article in this Codesandbox
Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.
While we believe that this content benefits our community, we have not yet thoroughly reviewed it. If you have any suggestions for improvements, please let us know by clicking the “report an issue“ button at the bottom of the tutorial.
This textbox defaults to using Markdown to format your answer.
You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!
Sign up for Infrastructure as a Newsletter.
Working on improving health and education, reducing inequality, and spurring economic growth? We'd like to help.
Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.