DEV Community

Cover image for An introduction to Vue.js - Chapter 2 - Components (Part I)
Moritz Schramm
Moritz Schramm

Posted on • Updated on

An introduction to Vue.js - Chapter 2 - Components (Part I)

Series overview

Chapter 1
Chapter 2
Chapter 3
Chapter 4
Chapter 5

Foreword

Before we start some short information.

Before you read the second chapter, please read the first one so that you have a basic setup we can work with. Thank you :)

I will always upload the code to this github repository.

Some of you ask me why I do not use "Single File Components" (.vue files). I decided to write a special chapter about that whole topic, show you how to configure your project to make use of them and tell you my opinion about this.

Our todays chapter will be more theory and less writing code.

Components

Components are one of the main parts or even the main part of Vue.js. But what is actually a component?

Let me check Wikipedia for you.

Web Components are a set of features [...] that allow for the creation of reusable widgets or components in web documents and web applications.

That is the basic definition of Web Components in the context of the W3C specs. But basically this although applies to Vue components. They are reusable widgets that you can use in your app. A widget could be a navigation, a list or even a simple button. I personally prefer naming my components with small letters and putting all files which belong together into one folder.

In Vue every component need to have at least 2 things:

  1. A name (obvious)
  2. A template (The rendered DOM that belongs to each component)

Lets take a look at the .js file of our last chapter:

import template from './hello.html';

export default {
    name: 'vg-hello',
    template
};
Enter fullscreen mode Exit fullscreen mode

We imported a template from a .html file and we exported a data object with two key-value-pairs. The two keys were name and template (if you are not familiar with the shorthand object property notation have a look here).

I prefixed my component name with vg- since it makes the work a lot easier when using third-party components. Later I will show you how to use those components in other components. There the name will be equal to our tag in the DOM.

Now let us have a short look into our current .html file:

<h1>Hello World</h1>
Enter fullscreen mode Exit fullscreen mode

Here we see the DOM which is rendered instead of the tag or when it is the root component (as it is for now), it replaces the mounted element in the initial DOM.

Reminder: Our index.html currently looks like that:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />

    <title>Vue Guide</title>
</head>
<body>
    <div id="app"></div>

    <script src="build.js"></script>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode

If we now start our app, open the dev tools and look at the DOM tree, we should see this:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />

    <title>Vue Guide</title>
</head>
<body>
    <h1>Hello World</h1>

    <script src="build.js"></script>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode

The direct replacement of the element and later the custom tags is something that I really like within Vue.js (Angular 4 for example renders the custom tags into the DOM).

Button

Now let us create another component, a simple button. We will use this button for the next chapters and it will develop more and more over time.

For now our button should be like:

  1. The HTML button tag
  2. Has the attributes class="button" and role="button"
  3. Has the text Click me!

Let us start with the template (src/components/button/button.html)

<button role="button" class="button">Click me!</button>
Enter fullscreen mode Exit fullscreen mode

This should be easy to understand. We have our button tag with class, role and the expected text. Now we need to define the .js file. (src/components/button/button.js)

import template from './button.html';

export default {
    name: 'vg-button',
    template
};
Enter fullscreen mode Exit fullscreen mode

I imported the template, named the button class vg-button and exported both. That is everything what we need to do. I will show you now how to use those components in other components. There are two ways and I will show you both.

Register the component on a global level.

For that we need to add some lines to our main.js.

import button from 'app/components/button/button';

Vue.component(button.name, button);
Enter fullscreen mode Exit fullscreen mode

Your main.js could now look like that:

import button from 'app/components/button/button';
import hello from 'app/components/hello/hello';
import Vue from 'vue';

Vue.component(button.name, button);

new Vue({
    render: (h) => h(hello)
}).$mount('#app');
Enter fullscreen mode Exit fullscreen mode

To use the button component in our hello component I adapt the hello.html:

<div class="app">
    <h1>Hello World</h1>
    <vg-button />
</div>
Enter fullscreen mode Exit fullscreen mode

As you can see I added an additional <div> around both elements since Vue requires exactly one root element per component.

If you now build and open your app you now should see the button. It has no functionality for now but it should be there. You can although add more:

<div class="app">
    <h1>Hello World</h1>
    <vg-button />
    <vg-button />
    <vg-button />
</div>
Enter fullscreen mode Exit fullscreen mode

Now should even see three. They should all have the same DOM, the same inner text and should all do nothing.

Register the component on a local level

That is basically the way I prefer since it is much more easier to test the rendered DOM in unit tests (we will see that in later chapters). I will use this way in the next chapters but I will not force you to use it (as always).

For that you need to adapt your hello.js. We need to import the component and then export the used components.

import button from 'app/components/button/button';
import template from './hello.html';

export default {
    name: 'vg-hello',
    template,
    components: {
        [button.name]: button
    }
};
Enter fullscreen mode Exit fullscreen mode

As you can see I added a new property to my object containing the used components. If we know use the same HTML in our template as before the button should still be there without registering them globally.

Done

I hope you like the guide. If you have any questions ask them on Twitter or in the comment section. I will try to answer a much as possible. I am happy about any possible feedback.

Next chapter will come in the next days.

Top comments (0)