<[object Object] defer="true" src="https://static.cloudflareinsights.com/beacon.min.js" token="0a1dcfae6c4348e2aa2d13c20d9fe61d">

# Components

Finally!

I hear you say.

TIP

First things first: if you want the official guide text on this subject, you can read it here.

We will now dip our toes into one of the more important features of this awesome framework. Knowing about them will help you wrap your head around how your apps do what they do, how the layout is described and a little bit of how the data is flowing through; at least that is the case for me.

# Syntax

You can register your components globally, which is making them available everywhere in your application:

Vue.component('my-component', // alternatively, 'myComponent'
    { /** configuration object goes here  **/ }
);
1
2
3

Note you can use camelCase or kebab-case for the string that gives your component a name, and Vue will understand either one to let you use it as a tag in your markup (we are specifically talking about a DOM template right now, you'll see why I mention this as we progress):

<my-component></my-component>
1

What do you think? In my opinion this is simple and elegant.

Moving on: did you notice the comment on line 2 of the JS snippet? We can pass a configuration object here too! Just like the one we have been working with, most of the options are available for our components to implement there.

There are a couple exceptions to what options you can use and a few extra ones, but here is an example of what my-component could look like:

let configObject = {
    template: `<div>Hello, {{ userName }} from my-component!</div>`,
    data() {
        return {
            userName: 'ackzell'
        }
    }
};

Vue.component('my-component', configObject);
1
2
3
4
5
6
7
8
9
10

So, we don't specify an el to mount to, because this is a component and not the root instance.

# template

What we define here though, is the template key. All the markup that will be ultimately rendered on the DOM is defined in this key.

You can use a template literal and inline it like I did in the snippet on line 2, or you could define it in your html by creating a special script tag like so:

 




<script type="text/x-template" id="my-id">
    <!-- Notice how this is the same code as above -->
    <div>Hello, {{ userName }} from my-component!</div>
</script>
1
2
3
4

And then referring to it in your configuration object by using the id you just specified:


 





let configObject = {
    template: '#my-id',
    ...
};

Vue.component('my-component', configObject);
1
2
3
4
5
6

# data

And lastly, another difference; can you spot it? Yes! Exactly right. The data key looks funky now.

What happened Axel? did you lie to me before? is this a typo? are you tired from writing this stuff really late at night?

Nope, I did not lie. Although yes, it is a bit tiresome to write late at night 😅.

Sorry about that, let's go back to the Components subject.

The data key is now a data() method on the object (which returns an object) so that this component can have its own state, and not all of the instances of this component are affected at the same time by the change in one of them.

We don't need to do this on the root instance because we only have one. Thus, it can be just a prop.

As a quick exercise, try changing the syntax on the example pen so that data is a property instead of a method on the object definition we have there.

It just doesn't work. ¯\(ツ)

Spoiler Alert: you should see something like the following logged out in some environments (at the time of writing this doesn't show in codepen):

[Vue warn]: The "data" option should be a function that returns a per-instance value in component definitions.

# Example I

See the Pen 04. Components (intro) by @ackzell on CodePen.

'Aight, let's keep moving on. Now that we know the basic structure of a component, we can talk about an option we can add to them in case we want to pass in information so that the component renders it, makes some calculation, etc.

We are talking about props, just like the sub-sub-tile suggests 😬. And they can be defined in many different ways but we'll stick to the quickest and simplest one right now. As we build more complex components and by extension apps, you'll notice we will use more "advanced" syntaxes to declare them.

Consider this snippet for the configObject in our my-component definition now:








 
 
 








 




let configObject = {
     template: `
        <div>
            Hello, {{ userName }} from my-component!
            <br>
            List of props:
            <ul>
                <li>{{ myProp }}</li>
                <li>{{ myProp1 }}</li>
                <li>{{ myProp2 }}</li>
            </ul>
        </div>
    `,
    data() {
        return {
            userName: 'ackzell'
        }
    },
    props: ['myProp', 'myProp1', 'myProp2']
};

Vue.component('my-component', configObject);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

So, first we'll add a new key in the configuration object: props. We'll specify an array of strings with the names of our props, as shown in line 19.

Then, most likely we want to render the values of those props within the component, so we need to add those in the template for it, like in lines 8-10.

This will enable you to now use the component, and pass in the props in the markup. Please note the use of the v-bind directive (aka :) when we are binding an expression as opposed to passing a raw value, like the string 'hello props' for my-prop1.


 
 
 


<my-component
    :my-prop="val"
    my-prop1="hello props"
    :my-prop2="val2"
    ></my-component>
1
2
3
4
5

Check out the following example, feel free to fork the pen and experiment with the different props, their names and binding values to them.

# Example II

See the Pen 05. Components (cont.) by @ackzell on CodePen.

Last Updated: 3/24/2022, 12:13:05 AM