Starting with Vue.JS

Ruth Newman
The Startup
Published in
6 min readJun 16, 2019

Whilst learning to code I have built sites with vanilla JavaScript, jQuery, React, and even Angular. React is growing in popularity and arguably Angular declining, but there is also a third pretender to the crown, currently far behind in popular but increasingly used and with many of its own adherents: Vue.js.

I have heard its similar to React, so I decided to check it out, and see how easy (or hard) it would be to build my first project with Vue.

To be able to start, I need to set up my computer to use Vue, this includes installing the Vue.JS CLI:

npm install -g @vue/cli

And the Vue developer tools (comparable to the the React developer tools, which I found immensely helpful when building projects with React. You can install the plugin for Chrome from the link here: https://chrome.google.com/webstore/detail/vuejs-devtools/nhdogjmejiglipccpnnnanhbledajbpd

I also looked at and bookmarked the Vue documentation: https://vuejs.org/v2/guide/

To start a project with Vue, there is a similar option to React’s create-react-app, but an even more succint command (the name my-first-vue-project obviously replaceable with whatever you want to call your project):

vue create my-first-vue-project

After changing to your project’s directory, the following command should then get the project up and running:

npm run serve

Visiting the site suggested (e.g. “http://localhost:8080/”), should take you to your initial application!

An alternative option to the two last commands above is to simply add the following command:

vue ui

This will take you to the browser and show the following screen:

Clicking on the create button will allow you to add a new project from the browser interface instead of through the command line:

Creating a new project brings you to a dashboard in the browser with a range of different options.

Navigating on the sidebar to ‘tasks’ will bring you to the option ‘serve’ which will do the same as the command line approach above:

Both of these options will generate a number of boilerplate files to get you started. Two key files in this instance would be App.vue and your first component file — HelloWorld.vue.

App.vue will look something like this:

<template>
<div id="app">
<HelloWorld msg="Welcome to Your Vue.js App"/>
</div>
</template>
<script>
import HelloWorld from './components/HelloWorld.vue'
export default {
name: 'app',
components: {
HelloWorld
}
}
</script>
<style>
#app {
font-family: 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>

That’s embedded styles within the file itself — which obviously you can change as you see fit.

As with React, you must have one element only nested at the first level, in this case a div with the id of ‘app’. Within the div, is the HelloWorld component, with props passed through. The syntax should be extremely readable for individuals already familiar with React.

Obviously its possible to create new components and pass different props:

For a task management application, this could be an array of tasks:

<script>export default {
name: 'app',
components: {

},
data() {
return {
tasks: [
{
id: 1,
description: 'Laundry',
completed: true
},
{
id: 2,
description: 'Ironing',
completed: false
},
{
id: 3,
description: 'Food shop',
completed: true
},
{
id: 4,
description: 'Clothes shop',
completed: false
}
]
}
}
}
</script>

To complete this idea, I need to create a new ‘Tasks’ component — I call this Tasks.vue and save it in the src/components directory:

<template>
<div>
<div v-bind:key="task.id" v-for="task in tasks">
<h4>{{task.description}}</h4>
<h4>Completed?: {{task.completed}}</h4>
</div>
</div>
</template>
<script>
export default {
name: "Tasks".
props: ["tasks"]
}
</script><style scoped></style>

When iterating through the array of tasks, as with React, its important to create a unique key (for vue this is with the vue-bind:key syntax as above). A common and logical option for this would be the object’s id.

I can refactor this by adding another file for a Task component (‘Task.vue’), and add additional functionality and styles, including a conditional background colour based on the completed status of a task, allowing for a task to be deleted when a button is clicked, and to toggle the completed status of a task when a checkbox is ticked:

<template>
<div class="task" v-bind:class="{'completed':task.completed}">
<p>
<input type="checkbox" v-on:change="showAsComplete">
{{task.description}}
<button @click="$emit('del-task', task.id)"
class="delete">X</button>
</p>
</div>
</template>
<script>export default {
name: 'Task',
props: ['task'],
methods: {
showAsComplete() {
this.task.completed = !this.task.completed;
}
}
}
</script><style>
.task {
background: crimson;
padding: 20px;
width: 300px;
margin: 0 auto;
color: white;
text-align: center;
font-size: 20px;
}
.completed {
background: green;
}
.delete {
background: white;
color: black;
font-weight: bold;
border: none;
padding: 5px 9px;
border-radius: 3px;
cursor: pointer;
float: right;
font-size: 12px;
}
</style>

The main application with simple styling looks like this:

With the Tasks component now looking structured like this:

<template>
<div id="tasks-container">
<div v-bind:key="task.id" v-for="task in tasks">
<Task v-bind:task="task" v-on:del-task="$emit('del-task', task.id)"/>
</div>
</div>
</template>
<script>
import Task from './Task.vue';
export default {
name: "Tasks",
components: {
Task
},
props: ["tasks"]
}
</script><style scoped>
#tasks-container {
margin-top: 30px;
}
</style>

Clicking the checkbox next to a task’s description changes its background colour:

The checkbox for ironing is selected — changing the background colour to green

This works both ways:

The App.vue file is also refactored to allow this all to happen:

<template>
<div id="app">
<h1 id="heading">My Tasks</h1>
<Tasks v-bind:tasks="tasks" v-on:del-task="deleteTask"/>
</div>
</template>
<script>
import Tasks from './components/Tasks'
export default {
name: 'app',
components: {
Tasks
},
data() {
return {
tasks: [
{
id: 1,
description: 'Laundry',
completed: true
},
{
id: 2,
description: 'Ironing',
completed: false
},
{
id: 3,
description: 'Food shop',
completed: true
},
{
id: 4,
description: 'Clothes shop',
completed: false
}
]
}
},
methods: {
deleteTask(id) {
this.tasks = this.tasks.filter((task) => task.id !== id);
}
}
}
</script>
<style>
#heading {
text-align: center;
margin-top: 20px;
color: orange;
}
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
background: black;
font-family: Arial, Helvetica, sans-serif;
}
</style>

This allows for a task to be deleted from the list on the front-end (i.e. as long as the site is not refreshed):

As with React — there are similar and highly useful Dev tools to monitor and debug the component tree, the passing of props as well as state management (to a degree).

Overall — it was an interesting initial exploration with Vue. It seems remarkably similar to React, but I will have to build more projects with it to truly understand the nuance of its advantages and disadvantages as compared to React.

I also especially want to look at state management with Redux’s sibling for Vue, VueX, but I’ll save that for another post, as I will making a full stack project with changes to data persisting after a site is refreshed.

--

--