Building your very first component in VueJs

James Samuel
codeburst
Published in
5 min readNov 1, 2017

--

Credit: npmjs.com

Before we delve into the world of components in Vue, let’s take a moment to understand what web components are, in application development.

For instance, my house is not far from a shopping mall where I do regular shopping just like everyone. This gigantic mall is made up of small chunks of blocks, laid and aligned on one another to form a large mass that enables us do shopping.

Credit: Cavity wall

In the same way, we can see components in web applications as blocks (small reusable chunks) carefully crafted together to form an application or even a bigger component called parent component.

The main difference between the shopping mall blocks and web components is that web components are blocks that encapsulate markup, HTML template, CSS, and Javascript rather than granites and cement materials.

Components in Vue

From the Vue official documentation, components are defined as custom elements that the Vue compiler attaches behavior to, and are created using a command Vue.component(tagName, options)

To demonstrate this, we will be creating a simple application that displays names of employees in ACME INT’L. For this purpose, we’ll create three (3) components, navbar-component, page-heading-component and staff-list-component.

To get started, we create an index.html page with this content:

<!---index.html--->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta.2/css/bootstrap.min.css">
<div id="app">
<navbar-component></navbar-component>
<div class="container">
<page-heading-component></page-heading-component>
<staff-list-component></staff-list-component>
</div>

</div>
<!--Include VueJs-->
<script src="https://unpkg.com/vue"></script>
<script src="main.js"></script>

Next, we begin to define how these components should behave and also register them with Vue.

Components can not stand on their own. They must be registered either with Vue instance or another parent component.

Rememeber, we once said components are registered using Vue.component(tagName, options). “Options” here is an object which can contain template, data, methods, props etc.

Now, our registered components should look like this, in main.js:

You notice we supplied a template (HTML elements) and also data that will be rendered on those HTML elements in staff-list-component, that gives you the capability to declare your HTML elements once and reuse them on multiple pages. Yeah! Those are the reusable chunks of code we were trying to describe in the previous analogy.

Obviously, it would be a pain in the ass to build complex projects this way. Wouldn’t it be nice if we could have each component stayed in one file, such that HTML elements are separate from javascript with a bit of CSS code? Of course yes! It’s called single-file component.

Single-File Component

A single-file component is a file with .vue extension and are built using browserify or webpack.
Single-file components can contain up to 3 sections:

<template>
<!---html template here -->
</template>
<script>
//javascript
</script>
<style>
/**style**/
</style>

Now, let’s rebuild ACME’s application using this approach. We’ll use webpack-simple to scaffold our app.
Before you run the following commands, ensure that you have npm and node installed.

We start by running these:

$ npm install -g vue-cli
$ vue init webpack-simple acme-app
$ cd acme-app
$ npm install
$ npm run dev

If you are able to do that successfully, your root folder should contain files and folders shown in this image.

We’ll create 3 files in src folder and name them NavbarComponent.vue, PageHeadingComponent.vue and StaffListComponent.vue respectively.

Change the content NavbarComponent.vue to this:

<!--NavbarComponent.vue--><template>
<nav class="navbar navbar-expand-md navbar-dark bg-dark mb-4">
<a class="navbar-brand" href="#">ACME INTL</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarCollapse"
aria-controls="navbarCollapse" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
</nav>
</template>

<script>
module.exports = {
data(){
return {}
}
}
</script>


<style scoped>

</style>

PageHeadingComponent.vue becomes:

<template>
<h1 class="text-center">{{title}}</h1>
</template>

<script>
module.exports= {
name:"PageHeadingComponent",
data (){
return {
title:"ACME's Staff List"
}
}
}

</script>


<style scoped>
</style>

And finally we update StaffListComponent.vue with this:

<template>
<table class="table table-bordered">
<tbody>
<tr v-for="staff in staffs">
<td>{{staff.name}}</td>
<td>{{staff.email}}</td>
<td>{{staff.role}}</td>
</tr>
</tbody>
</table>
</template>


<script>
module.exports = {
name: "StaffListComponent",
data (){
return {
staffs: [
{name: 'John Doe', email: 'John.doe@acme.org', role: 'Central Executive Officer'},
{name: 'Rebbecca Dan', email: 'rebbecca.dan@acme.org', role: 'Backend Developer'},
{name: 'Tope Joshua', email: 'tope.joshua@acme.org', role: 'Financial Analyst'},
{name: 'Alima Fatima', email: 'alima.fatima@acme.org', role: 'Deputy CTO'},
{name: 'Sikiru Oluwaseun', email: 'sikiru.oluwaseun@acme.org', role: 'Project Manager'},
{name: 'Larry Greg', email: 'larry.greg@acme.org', role: 'Senior Developer'},
{name: 'Inna Brown', email: 'inna.brown@acme.org', role: 'Community Manager'},
{name: 'Tunde Ogundipe', email: 'tunde.ogundipe@acme.org', role: 'Chief Technology Officer'},
{name: 'Bald Kuma', email: 'bald.kuma@acme.org', role: 'Human Resource'},
{name: 'Ramon Aduragbemi', email: 'ramon.aduragbemi@acme.org', role: 'System Administrator'},
]
}
}
}

</script>


<style scoped>
</style>

If we take a look right at the src folder the second time, we’ll see App.vue that was created during the scalfolding process. We’ll make this our parent component where all other components (PageHeadingComponent, NavbarComponent and StaffListComponent) will be registered as children.

You must have noticed that we assigned our code to a special object module.export. This exposes the logic of our component. Functions or variables defined in single-file components are only visible within their scope and since they must be registered with a parent component (App.vue), we must therefore export them.

Let’s go ahead and edit our App.vue to:

<!--App.vue (Parent component)--><template>
<div id="app">
<navbar-component></navbar-component>
<div class="container">
<page-heading-component></page-heading-component>
<staff-list-component></staff-list-component>
</div>
</div>
</template>

<script>
import PageHeadingComponent from './PageHeadingComponent.vue'
import StaffListComponent from './StaffListComponent.vue'
import NavbarComponent from './NavbarComponent.vue'
export default {
name: 'app',
components: {NavbarComponent, PageHeadingComponent, StaffListComponent}, //Register other components
}
</script>

<style scoped>
</style>

As at now, we have registered three components with App.vue but App itself is yet to be registered. We go ahead and register it with the root instance defined in src/main.js

Let’s make some changes to src/main.js

//src/main.jsimport Vue from 'vue'
import App from './App.vue'

new Vue({
el: 'app',
components:{App}
})

And finally, edit index.html to:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>acme-app</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta.2/css/bootstrap.min.css">
</head>
<body>
<app></app>
<script src="/dist/build.js"></script>
</body>
</html>

If you check your browser now, you should see an output simillar to this.

Components are a very important feature of Vue as they allow you to create code that is highly reusable and self-contained.

Complete source code of this post can be found here.

--

--