Render Functional Components in Vue.js

Alex Jover Morales

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.

Template

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:

FunctionalButtonTemplate.vue

<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

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:

FunctionalButtonJSX.js

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}.

JSX Function

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:

.babelrc

{
  "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:

FunctionalButtonFunction.js

export const FunctionalButton = ({ data, children }) =>
  <button {...data}>
    {children}
  </button >

Wrapping Up

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

  Tweet It
✖ Clear

🕵 Search Results

🔎 Searching...