Vue js Single File Components. Vue CLI. And example of how to build reusable components

Build on Vue

When building a new project programmers are able to do the given task by using different techniques. However, the task should not be “solved by one way”, but rather “solved by the most optimal and reusable way” because of that in programming process there are multiple ways of dealing with things differently and logically. Therefore, when preparing a program that will solve some problem, it is necessary to prepare background jobs in accordance with modern requirements and in line with programming trends. Thus when using the Vue.js framework during the preparation of the front end, we need to use standardized methods that are most appropriate and easy to do our job. So in this article we will talk about how to set up Vue globally, how single file components work and how to immediately begin coding by using prototype projects generated by Vue CLI.

Vue Single File Components consist of 3 parts:

  1. template
  2. script
  3. style

So, we are preparing the skeleton of the project view in template part by using normal html, providing the information on the page. In part of the script, we are preparing the logic that keeps data, processes, methods and also performing various operations. Within style tag, we have ability to perform design operations globally and scoped (only effected current component) way.

To make easy of use single file components, easily create new project and perform other actions during development process Vue team developed command line interface called as Vue CLI. So, by using predefined commands you can:

  1. interactively create new project
  2. begin the job without wasting time on configuring tools
  3. add different plugins
  4. and also create visual interface and manage it from admin panel and much more…

Before using Vue CLI there must be node installed on your system to be able to use npm commands properly. To do so, follow the link and setup appropriate node package for your operating system. After you must install Vue globally into your system. (https://cli.vuejs.org/guide/installation.html). So lets start installing vue and doing some amazing things!

First open a terminal and run following command:

npm install -g @vue/cli
//or yarn
yarn global add @vue/cli

After installing required packages you can use “vue” command globally and create new project. To test the installation is successfully finished run the following command:

vue --version

It will show you the version of Vue. If you successfully see these information this means that Vue is now working globally in your system.

To create new project we will run this command vue create “project_name” in appropriate directory for your wishes. Let’s start by creating a new project by marking the project’s name as vue-app.

vue create vue-app

At this time, you will face an appearance like below. (it is necessary to perform some operations on interactive choices for windows users. You can find out about this in detail. https://cli.vuejs.org/guide/creating-a-project.html#vue-create)

Vue CLI v3.5.1
? Please pick a preset:
❯ default (babel, eslint)
Manually select features

You can change selection using arrow keys. If you chose first option it will create default project and configure base settings to make able to start project immediately. But in other way which is manually you can select multiple options like router, vuex or pwa and also activate different plugins during creation process if you know that later you will use these tools. After selection there will be created folder named “node_modules” (needed plugins, libraries etc.) with all dependencies in it. Then open the project with an editor (sublime, atom) and you will see there are multiple folders and configuration files. The main folder to write Vue codes is “src” and there are automatically created Vue components inside of it. Inside this folder all Vue operations will be done and then compiled to the form of code which can be understood by browsers. If you open file named as package.json in root directory you can see there are 3 command line option to be able run from terminal:

  1. serve — start development server on localhost to see code changes live
  2. build — compress and build for production
  3. lint — analyze dangerous scripts and coding style

So to see project alive open terminal and change current directory to the root directory of newly created Vue project then run command : npm run serve . After this operation you will see information message as below:

App running at:
- Local: http://localhost:8080/
- Network: http://192.168.1.188:8080/

Enter the link (http://localhost:8080/) provided in message and there you will see the live version of your default Vue project. To make it clear lets explain what happens in background. When you run command npm run serve the codes which written in “src” folder are compiled and auto injected into index.html file inside public directory based on predefined Vue configurations. And if you change anything inside src directory it will automatically refresh the content of page. But all these processes were automated by Vue creator community and all necessary configuration files, tools are compacted into structured form to background. Other way you must configure tools like webpack, babel and others to compile “.vue” files to the form which browsers will understood.

Now lets begin to see how default Vue project is structured. Inside src folder there is main.js file which holds the root javascripts and creation of Vue app.

import Vue from 'vue'
import App from './App.vue'
new Vue({
render: h => h(App),
}).$mount('#app')

Then open App.vue file and there you will see a div tag with ID “app”. This means that our app will be structured inside this div hierarchically. Inside script part of App.vue file you can see that HelloWorld component is imported locally. This means that HelloWorld (<HelloWorld/> inside html) can do all operations - accept property, fire event and so on.

Because we’ve already created the project and get a little information about how project is structured we can start real world example of how to create and use components. Lets create news publisher site main page and use Vue abilities to make the work effective and simple. To do so, create NewsHolder.vue file inside src/components directory and add code which must be inside template. (if you want to see changes immediately run : npm run serve in the root directory of project and go http://localhost:8080/ on browser.)

<template>

</template>

<script>
export default {
name: "NewsHolder"
}
</script>

The template tag is specific for Vue and keeps html of view inside. Inside of template it is important that one html tag must surround all inner tags. Other way Vue will show error on console to do so. Inside script section there is firstly typed component’s name. When you want to call this component you will use this name. So now lets add news information and a method that demonstrates that reader read news.

So firstly inside template tag we added a div tag and inside it we created form of html. The second div tag will be looped by using v-for directive as seen in the code and it will create 3 news information because of we defined news array inside data section of our component. So in this file you can see that all logic based on news holder component are isolated from other parts of site. This gives us ability to divide project multiple logical parts. Let’s continue and create 2 different part of our site. The first one is links holder which routes different pages of our site.

LinkHolder.vue

Here you can see that 3 links were looped and showed in html section. These links are hold inside of links array. On <a> tag you can see route URL binding which is provided by Vue js. And also the name of route showed inside {{}} brackets.

Lastly lets create adds holder component:

AddsHolder.vue

Inside this component we are holding the adds section of our site. So there are multiple adds inside of adds array and they rendered by looping inside template section of our component.

As you can see we prepared 3 different part of our site in different files (all inside “src/components” directory). This type of structure gives us ability to edit and update code easily and do later changes the fastest way. But I know that you thinking we only created parts of our site but neither added them into main view nor registered them. So let’s begin to do last operations to show created components in our main view. To do so, we need to import components into App.vue and show them in html proper sections. You can copy and paste below code and see the changes immediately if everything done correctly:

For simplicity I have used bootstrap and added it into public/index.html as link and it will be ready to use over cdn.

<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">

Now you can see 3 components are included into App file and placed inside html by adding just their names. You can see that names of components are typed by dashes. So the name of component calling form is depend on how you defined component name inside its core .vue file. If you defined — name: “NewsHolder” then you can use both <news-holder> and <NewsHolder>. But if you define name: “news-holder” then you can only use it as <news-holder>.

In scripts part you can see that components property is holding the names of imported components into this (App.vue) component. This is local registration form of vue components and here it is okay to use it like this. Because of that you are not registered components globally you must import them into parent component and register. But in practice you can have both local and global components to make your work more effectively. Consider that you will use a component in different parts of site multiple times. So it will be useless to import everywhere and use component again and again. The correct way is to register component globally and use them without importing anything. This gives us the opportunity use local components by importing them when needed and global components multiple times where we need without importing them. Let’s now convert our existing components to global version just for example to show how to register components globally and also optimize project structure more useful version.

First we will create news folder inside components folder because of that holding all components based on specific section is good practice. Our project structure now like in below image:

And after moving our components into news folder we need to create index.js file to register them globally. You can also register all components inside main.js file but in practice it is not good to do all registration in one file. Therefore we create index.js file for news folder and its components and later we import it into main.js file. So register components globally as below:

//news/index.js

import Vue from 'vue'
import NewsHolder from './NewsHolder';

Vue.component('news-holder', NewsHolder);
Vue.component('links-holder', require('./LinksHolder').default);
Vue.component('adds-holder', require('./AddsHolder').default);

As you can see firstly we need to import Vue itself then we can add components to it. During registration process you can use multiple form of registration. Here I have showed 2 version

  1. You can import component then add it — Vue.component(registration_name, imported_name);
  2. You can directly require component — Vue.component(registration_name, component_paht); (we must add .default after requiring component because of change showed in this link -https://github.com/vuejs/vue-loader/releases/tag/v13.0.0)

After registration process completed one last step is import index.js file into main.js file to show compiler that also import these script to building process. So in main.js file we require index.js:

import Vue from 'vue'
import App from './App.vue'

Vue.config.productionTip = false;
//if no js file name occurs then it will look for index.js.
require('./components/news');

new Vue({
render: h => h(App),
}).$mount('#app');

So news components are now registered globally to main Vue object. After this process we can delete not needed imports from App.vue because of that we already registered them root Vue object and so the last form of App.vue is:

In genral keeping parts of site in different and logically divided components gives us opportunities to find needed file fast, upgrade components more flexible and logically, create reusable components and use them wherever you need. So if we consider component as reusable function we register it once and use it whenever we need and also upgrade for our needs. To show an example let’s create reusable component and add new fuctionalities later when we need.

As you can see below I have created new component named as MyButton and added some props to it. This component is located inside of components/globals folder considering that we will use it globally around the site.

There you can see that default class is added class=”btn”. But also optional classes could be added to this button later by accepting props (bClass) from parent component. Here also the function (clickFunction ) which will be executed when clicked on button and it will be passed from outside of component. Lastly the button text also can be added from outside or it has default value to show if no bText prop occurs. After creating MyButton.vue component then you must register it globally as we did for news folder before. Then we will use it inside NewsHolder component and see it in action: (html part changed a little bit)

<div class="row">
<div class="col-6">
<my-button :click-function="showDate" b-class="btn-danger btn-sm" b-text="show year"></my-button>

</div>
<div class="col-6">
<button type="button" class="btn btn-outline-primary btn-sm float-right" v-on:click="readNews(index + 1)">Read</button>
</div>
</div>

While looking the code you can see that the purpose of using my-button component in this section is to show date which binded to it (:click-function=”showDate” ). The function is added to methods property in NewsHolder component

showDate(){
alert('Year is: ' + (new Date()).getFullYear())
}

After all this process done when you click the button it will show you an alert box with the information of current year. Also you see that b-class and b-text (this have default value to use if no provided outside) props also passed to component but this time not using “:” because of that “they are just text not variable”. So b-class adds red and small size which is bootstrap classes and b-text gives a name to component in currently used place. Refresh the page and click the newly created function. You will see the year alert box on screen.

But when creating this button component I noted that it will be reusable and upgradeable for later purposes. Think that you need the ability to disable button and after some operations finished then make button clickable. To do so, we need to add a prop to MyButton component and we name it as “isDisabled”.

//html changes in MyButton.vue
<button class="btn" :class="bClass" @click="clickFunction" :disabled="isDisabled">{{ bText }}</button>
//props adding
isDisabled: {
type: Boolean,
default: false
}

After this additions we can now keep our button component disabled and activate it later when we need to click it. To show it in action let’s create another my-button component and give it different functionalities.

So newly created my-button component properties are different than first one. Also newly created deactivation ability is used by disabling second my-button component while condition is true. The condition is defined as variable named isTourEnded and default value is false.

<my-button :click-function="tourEnded" b-class="btn-success btn-sm ml-3" b-text="end tour" :is-disabled="!isTourEnded"></my-button>
//and data
data() {
return {
isTourEnded : false
}
}

I also changed show date function to stop time 2 seconds then change the value of isTourEnded to true. Thus second my-button component will be activated after first my-button clicked operations have done.

As I mentioned above you now see that how effective is to create reusable components and upgrade it later for our needs. Generally using components in our development process will give us more advanced control over code flow.

What’s Next Level?

In this article I have showed that how effective it can be to use components and divide code into multiple logical parts. But Vue’s power is not all about these. While development process if you want to create Single Page Application (SPA) you will use Vue router. Then if emitting events and passing props through deep components will make you angry and you will look for a way to do more structured data organization. Here Vuex will come to help you which is state management library for Vue js. Later you will need to do form validation in front end section then you will use veevalidate library. And also if you need to do some complex operation like date picking you will use already created vue2-datepicker component in your site. Lastly if you want to create some logic that will be repeated major parts of your site then you will create reusable components for this purpose. As a result, you will be able to accomplish the development process in a more intuitive, evolving and self-contained form of each piece. So I advise you to learn Vue framework, its other products, and use its superior features to perform fast and efficient development process.

Good coding days :)

Helpful links

  1. Vue ready tools— https://github.com/vuejs/awesome-vue
  2. Vuex state management — https://vuex.vuejs.org/guide/
  3. Vue routing — https://router.vuejs.org/
  4. Windows git bash installation — https://gitforwindows.org/
  5. Vue design — https://vuematerial.io/
  6. Ready project in this article — https://github.com/Abdulla1995/vue-news-page