Tutorial

Functional Components in Vue.js

Published on January 22, 2018
Default avatar

By Alex Jover Morales

Functional Components in Vue.js

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.

Functional components are very popular in the React community. They allow to create simple components in a neat way just by passing a context, making them very simple to reason about.

What’s a Functional Component

You can think of a functional component to be the equivalent of a function, brought to the component world. That said, it’s a component that takes a render context and returns the rendered HTML.

A functional component is:

  • Stateless: it doesn’t keep any state by itself
  • Instanceless: it has no instance, thus no this

By its nature, two of its use cases are presentational and higher order components.

Creating a Functional Component

To define a functional component, you must create an object with a functional: true property and a render function. Let’s create an example of a FunctionalButton component:

FunctionalButton.js
export default {
  functional: true,
  render(createElement, context) {
    return createElement('button', 'Click me');
  }
};

Render Context

The context argument you see on the render function is known as the render context. It’s an object containing the following properties:

  • props
  • children
  • slots: function returning a slots object
  • parent
  • listeners
  • injections
  • data: an object with contains all the previous properties

Let’s try some out. Say you have an App.vue component where you import FunctionalButton.js to use it in its template:

App.vue
<template>
  <FunctionalButton>
    Click me
  </FunctionalButton>
</template>

That way it’s possible now to use children property instead of the hardcoded ‘Click me’:

FunctionalButton.js
export default {
  functional: true,
  render(createElement, { children }) {
    return createElement("button", children);
  }
};

Passing Props

Let’s have more fun with this component; what’s a button without a disabled property?

App.vue
<template>
  <FunctionalButton>
    Click me
  </FunctionalButton>
</template>
FunctionalButton.js
export default {
  functional: true,
  render(createElement, { props, children }) {
    return createElement('button', { attrs: props }, children);
  }
};

Keep in mind that button is an html tag, not a component, so props would have no effect. Thus why the use of the attrs property from the createElement arguments, which gives a slightly different structure to the render context.

Trigger Events

Given the fact that functional components have no instance, the event listeners come from the parent on the context.listeners property.

With that in mind, you can implement a click event like so:

App.vue
<template>
  <FunctionalButton @click="log">
    Click me
  </FunctionalButton>
</template>
FunctionalButton.js
export default {
  functional: true,
  render(createElement, { props, listeners, children }) {
    return createElement(
      'button',
      {
        attrs: props,
        on: {
          click: listeners.click
        }
      },
      children
    );
  }
};

All Together

Remember that data includes all the createElement context properties, so we can rewrite the FunctionalButton this way:

FunctionalButton.js
export default {
  functional: true,
  render(createElement, { data, children }) {
    return createElement( 'button', data, children );
  }
};

Think how easy it would be to create a wrapper component, also known as Higher Order Component (HOC), that adds something to a component. For example, we could prepend "Hello " to the button text:

createElement('button', data, ['Hello ', ...children]);

Wrapping Up

You’ve seen what functional components are and what role they play. Here I’ve been using the render function syntax in order to show the lower-level details, but we’ll explore other ways to render functional components in future articles.

Find all the code from this Button example in this Sandbox

Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.

Learn more about us


About the authors
Default avatar
Alex Jover Morales

author

Still looking for an answer?

Ask a questionSearch for more help

Was this helpful?
 
Leave a comment


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!

Try DigitalOcean for free

Click below to sign up and get $200 of credit to try our products over 60 days!

Sign up

Join the Tech Talk
Success! Thank you! Please check your email for further details.

Please complete your information!

Get our biweekly newsletter

Sign up for Infrastructure as a Newsletter.

Hollie's Hub for Good

Working on improving health and education, reducing inequality, and spurring economic growth? We'd like to help.

Become a contributor

Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.

Welcome to the developer cloud

DigitalOcean makes it simple to launch in the cloud and scale up as you grow — whether you're running one virtual machine or ten thousand.

Learn more
DigitalOcean Cloud Control Panel