DEV Community

Giuseppe
Giuseppe

Posted on • Edited on

Have you ever heard about Vue functional components?

First of all: welcome to my blog! This is my first post and I want to greet you and say a big thanks for coming here!

So, let's go forward with the real topic of this post.

Table of Contents

  1. What is a Vue component?
  2. Functional component
  3. How can I write a functional component?
  4. TL;DR

What is a Vue component?

Basically a component is a reusable Vue instance with its own state, props, computed props, methods and lifecycle.

Cool features, right? Yes, they are... But try to ask to yourself: "Do I always really need of all these features? Is it always necessary to have reactive data and the whole component's lifecycle?"
The answer to all these questions is: No, you don't.

Sometimes you just need to have a component whose main gol is to render something.

I know, now you're asking to yourself: "Could I use a normal component to do that?"
The answer is: Yes, you can.

But, now, let me ask you a question: "Why should you use a normal component for doing that when you can use a functional component?"

Functional component

A functional component is, basically, an instanceless component without the lifecycle. Nothing else. It's just a simple function whose goal is to render some data.

For this reason you can also call it presentational component or dumb component.

Since this kind of components don't have instances, they are faster, lighter and rendered once. As you can see I've written lighter because, without the whole lifecyle and the reactivity system, the final bundle is lighter, which means:

  • less JavaScript code to parse;
  • less memory to handle.

All this stuff gives to your applications better performances and browsers will be grateful to you.

How can I write a functional component?

I'm pretty sure, at this point, you have this question spinning around in your mind. I want to be as clear as possible, so I'll answer you with some code.

What I'm going to do is to code a normal component and transform it into a functional component.

Normal component

<template>
  <div class="smart-component">
    <span class="smart-component__prop">{{foo}}</span>
    <span class="smart-component__prop">{{bar}}</span>
  </div>
</template>

<script>
  export default {
    name: "SmartComponent",
    props: {
      foo: {
        type: String,
        required: true
      },
      bar: {
        type: String,
        required: false,
        default: "Default value"
      }
    }
  };
</script>
Enter fullscreen mode Exit fullscreen mode

Cool, isn't it? But do you know what happen each time the SmartComponent is instantiated?

Basically Vue creates its instance, adds reactivity and mount the component. All useless stuff, since the SmartComponent is not going to use reactivity. And, as I've already said, the final bundle will be heavier.

Let's rewrite it in the functional way.

Functional component

<template functional>
  <div class="dumb-component">
    <span class="dumb-component__prop">{{props.foo}}</span>
    <span class="dumb-component__prop">{{props.bar}}</span>
  </div>
</template>

<script>
  export default {
    name: "DumbComponent",
    props: {
      foo: {
        type: String,
        required: true
      },
      bar: {
        type: String,
        required: false,
        default: "Default value"
      }
    }
  };
</script>
Enter fullscreen mode Exit fullscreen mode

That's all. Nothing special. As you can see, I've only changed a couple of things:

  • I've added the functional keyword to the template block;
  • I've prepended the props keyword to foo and bar props.

The functional keyword

Well, as you can easily guess, the functional keyword is used to say to Vue: "Hey, I'm going to write a functional component! Don't overload it adding the whole lifecycle and the reactivity; I don't need them!"

The props keyword

Since functional components don't have an instance, the this keyword will be undefined. So, to read props, you need to prepend the props keyword to each prop.

Woah

I know, I know... You're asking to yourself: "WTF? I don't see any this before SmartComponent props!"
The reason is that Vue automatically binds props, methods, computed and $options objects to the component instance.
So, basically, in this scenario {{foo}} and {{bar}} are short versions of {{this.foo}} and {{this.bar}}.
Keep in mind: this works ONLY within the <template> block; in the <script> block you MUST put the this keyword before props, methods, computed and $options, otherwise you'll get an error.

N.B. There is another way to write functional components and it's with the usage of render functions, but I'll write a more detailed post about them.

TL;DR

When you don't need to have a reactive state and the whole component lifecycle, for better performances, you should use functional components.


Follow me on

If you liked the post, you might offer me a ☕️ on PayPal. 🙂


Top comments (1)

Collapse
 
rhymes profile image
rhymes

Welcome to DEV!