Getting Started with Vue.js

Released in 2014, Vue.js is a lightweight front-end framework similar to React and Angular. React and Angular dominate the front-end framework market share. However, Vue is the fastest growing framework. Since Vue has a smaller ecosystem, Vue has fewer plugins and libraries. This also means there are fewer resolutions on stack exchange for Vue issues that you may encounter.

While Angular was created by Google and React was created by Facebook. Vue was created by Evan You (who previously worked with Angular at Google). He initially created Vue as a framework for prototyping. Since Vue is not tethered to a corporate sponsor, Vue is dedicated to supporting its users.

Vue’s core libraries and tools are supported by Vue such as Vuex (similar to Redux), Vue Router, Vue Devtools, and Vue CLI. On the other hand, React relies on 3rd party libraries such as Redux, React-Router-DOM, etc.

Each Vue component has three sections: template (HTML), script (Vue properties), and style (CSS). The logic in the scripts are written in JavaScript so I would strong suggest you brush up on your JavaScript skills.

Unlike React, which uses JSX for the view, Vue utilizes plain HTML which reduces the learning curve and makes it easier to port legacy apps made is HTML. Similar to other front-end frameworks, Vue implements a component-based approach to create single page applications (SPA). Like Angular, components are inserted into the view via an assigned HTML tag.

As we know, making changes to the DOM is time-consuming. Therefore, Vue creates a virtual DOM which mirrors the real DOM. Any time there is a change in the state, Vue tracks the difference between the new state and the old state. This difference is applied to the real DOM.

Vue implements two-way binding which is a connection between the data and the view. Whenever there are changes in the data, it will change the view. Additionally, changes in the view will cause changes in the data.

Vue Life Cycle: Here is a diagram showing the Vue life cycle depicting how components are created, changed, and mounted. You may not understand it at the moment but you can refer to this diagram as you go through this article.

Import Vue in the head:

<script src=”https://cdn.jsdelivr.net/npm/vue@2.6.12"></script>

Initiate a new Vue instance in the body of the HTML:

  1. In the HTML template, create a div with id=’app’
  2. Inside <script></script>, create a new Vue instance that targets this div by setting a property inside the Vue instance to el: ‘#app’
  3. Pass data into the the instance by setting a property inside the Vue instance to data: {yourProperty: ‘youValue’}
  4. Pass methods/functions into the instance by setting a property inside the Vue instance to methods: {yourMethod: function() {}}. Make sure to utilize the “this” keyword to access methods and properties created in the Vue instance.
  5. In order for us to see how the methods work, create an input form with a directive called v-on:input=”changeTitle.” Next, inside of the methods property of the Vue instance, create a property changeTitle: function(event) {this.title = event.target.value}. Normally, this would not be bound to the data property. However, in Vue, methods that use the keyword this will have access to the data properties and method properties (functions).
<div id="app">
<!-- v-on is an directive which sets an event listener to fire the
changeTitle method whenever there is a change in the input -->
<input type="text" v-on:input="changeTitle" />
<p>{{title}}</p>
</div>
<script>
new Vue({
// targets the div with id=app
el: "#app",
data: {
title: "Hello World!",
},
methods: {
changeTitle: function(event) {
// this will access all the properties stored in data and all the methods
// stored in methods
this.title = event.target.value;
},
},
});
</script>
  • The only properties or return values that can be rendered in the DOM from {{}} are strings.
  • We cannot use {{}} inside of any HTML attribute. Instead, if you need to access a property or method in the HTML attribute, you must bind the attribute using the following directive Vue-bind: yourAttribute=’propertyName’
<div id="app">
<p>{<a v-bind:href="link">google</a></p>
</div>
<script>
new Vue({
el: "#app",
data: {
link: "http://google.com",
},
});
</script>

Directives: Directives are placed inside of html tags which provide instructions for Vue. Here are some common directives

  • v-once ==> the element will only render only once. Therefore, if a function or element causes the element to change again, the element will not rerender.
  • v-html ==> By default, Vue escapes (does not render) HTML elements. This behavior prevents XSS attacks. If the code has been sanitized, you can override Vue to render HTML by using v-html=’<p>hello</p>’
  • v-bind ==> Pass data from the Vue instance into the HTML template. For shorthand, you can replace v-bind with “:”
  • v-on ==> Pass data from the HTML template to the Vue instance. This directive is typically used with event listeners. Shorthand is (@). Some common v-on directives are @click (buttons), @change (checkboxes, text fields), @yourEmittedEvent (in the parent, you can listen for emitted events from the child), @submit.prevent (submitted a form), @blur (user clicks outside of the element).
  • v-model ==> Two way data binding which means data is passed from the script to the template and template to the script. Under the hood, if you use v-model on custom components, it will pass the model-value prop into the child component. In addition, v-model will setup an update:modelValue event listener in the parent and will emit an “update:modelValue” event. Therefore, the parent will know when there are changes to the child component.
  • v-if ==> If true, attaches the element (along with all children) to the DOM. If false, removes the element (along with all children) from the DOM.
  • v-else-if ==> If the most recent v-if is false and the v-else-if condition is true, the compnent/element (along with all children) will be added to the DOM. Otherwise, the element (along with all children) will not be inserted into the DOM. Note, v-if needs to be on the same type of HTML tag.
  • v-else ==> If the most recent v-if is false and v-if-else statements are false, the v-else element (along with all children) will be added to the DOM. Note, v-if needs to be the same type of HTML tag.
  • v-show ==> If true, the element will be displayed. If false, it will be hidden. Note, the element is not removed from the DOM (as is the case with v-if)
  • v-for ==> A for loop that will iterate over an array. You can access the item and its index with string interpolation {{}}.
<ul>
<!-- a for loop that creates a variable ingredient -->
<li v-for="(ingredient, index) in ingredients" :key="ingredient">
{{ingredient}} {{index}}
</li>
</ul>
  • v-for ==> You can also loop through an object. You can access the keys and values as shown below
<div v-for="(value, key) in person" :key="value">{{key}}: {{value}}</div>

Arguments: Within the directive, you can pass arguments into the functions inside of (). Note, by default, you can access the event object (i.e. event.target.value) without passing in the event parameter. Although not necessary, you may pass in $event as the last argument when calling the function.

<div id="app">
<p>{{counter}}</p>
<p v-on:mousemove="updateCoordinates(2)">Coordinates: {{x}} / {{y}}</p>
</div>
<script>
new Vue({
el: "#app",
data: {
counter: 0,
x: 0,
y: 0,
},
methods: {
updateCoordinates: function(step) {
this.x = event.clientX;
this.y = event.clientY;
this.counter += step;
},
},
});
</script>
  • Event Modifiers: Event modifiers specify which event you are looking for. In the example below, the .enter modifies the v-on:keyup so that the event listener will only fire for keyup on the “enter” button.
<div id="app">
<!-- You can add .enter to modify the keyup event listener -->
<input type='text' v-on:keyup.enter="alertMe"></p>
</div>
<script>
new Vue({
el: "#app",
data: {},
methods: {
alertMe: function() {
alert("Alert");
},
},
});
</script>
  • Functions in the HTML template: You may write simple javascript functions inside of the directive. However, you may not use if/else or for loops. You may use ternary statements

Vue Instance Properties:

  • el: refers to the HTML element to apply the Vue instance
  • data: The data property returns an object that represents the state. Properties stored in data can be accessed in the HTML template using {{propertyName}}. You will typically store strings in the data object. Of note, within the data object, you cannot access other parts of the data object. For example, inside of the data object, the following is invalid:
data: function() return {
count: 0,
count2: this.count + 1
},
  • methods: You can write methods in the methods property. You can call the method the same way as any other JavaScript function (i.e. to fire a method on the on-change listener: @change=”yourMethod()”). You may access data in your methods, use the “this” keyword. To handle the event object of an HTML element, do not include the parentheses (@change=”yourMethod”). Then add the “event” parameter when you define your method as shown below.
<template>
<input type="text" @change="logNumber" />
</template>
<script>
export default {
methods: {
logNumber(event) {
console.log(event.target.value);
},
}
};
</script>
  • computed: At times, you may want to store data that is derived by logic. As such, Vue has a “computed” property. One of the main reasons we use “computed” is so that our component can react to changes in the “store” (Vuex). The computed property is a function that returns a value. You may access data using the “this” keyword. If any of the variables or dependencies change inside of the computed property, the computed method will fire again. Using the example below, output will only fire if this.count changes. You cannot use computed methods with asynchronous calls. Of note, unlike watch properties, computed properties should return a value. Also, unlike watch properties, computed properties can be accessed in the template using {{}}.
computed: {
output: function () {
return this.count;
},
},
{{ output }}
  • watch: Watch methods only fire when a defined property changes. Watch methods can also handle asynchronous functions. To use watch, set the watch property to a property in the data object that you want to watch for. In the example below, we set the watch property to “count” since the data property is also “count.” Whenever the “count” changes, the watch method will fire. Next, write a function that takes in a “value ”parameter (the value parameter represents the data property). No return value is needed. Note, unlike functions in methods or computed, you do not need to call the watch method anywhere in the template. In the example below, if the count property changes, the count will be reset to 0 after 2 seconds. Further note, only the outer function has access to “this,” so we need to store the value of “this” in a variable so that the callback function inside of setTimeout (aynchronous function) can access it.
data: {
count: 0,
},

watch: {
count: function (value) {
console.log(value)
const vm = this;
setTimeout(function () {
vm.count = 0;
}, 2000);
},
},
const vm = this;
setTimeout(function () {
vm.count = 0;
}, 2000);
},
},
  • provide: function() {} ==> Delivers data to child components. It should be noted that non-primitive data (arrays, objects) can be “provided” to other components which will effectively be added to the receiving component’s data. It should be noted that you cannot replace the array/object because the reference to the old array/object will be overwritten by the new array/object. However, all the components that were using the old reference will maintain their reference and will not acknowledge the new array. To effect changes in an array, you must use push, unshift, etc on the original array. To effect changes in an object, you must change the keys or values of the original object.
  • inject: [] ==> Receives data “provided” by the parent
  • components: Import and register components that will be used inside of the component. Note, you may register a component globally using Vue.component() and it will available throughout your app.
  • props: In the child component, we can access the properties that were passed into the child component via the props property.

Dynamic CSS Styling: Set :class = “{‘yourClass’ = true}” to add a dynamic class to an HTML element. In the example below, we add a dynamic “red” class.

<head>
<style scoped>
.demo {
width: 100px;
height: 100px;
}
.red {
background-color: red;
}
</style>
</head>
<body>
<div class="demo" :class="{'red': attachRed}"></div>
</body>
<script>
new Vue({
el: "#app",
data: {
attachRed: true,
},
});
</script>

Computed Styling: Toggles red and blue background

<head>
<style scoped>
.demo {
width: 100px;
height: 100px;
}
.red {
background-color: red;
}
.blue {
background-color: blue;
}
</style>
</head>
<div class="demo" :class="divClasses"></div><script>
new Vue({
el: "#app",
data: {
attachRed: true,
},
computed: {
divClasses: function() {
return {
// red: true/false
red: this.attachRed,
// blue: true/false
blue: !this.attachRed,
};
},
},
});
</script>

Name Styling: Displays a blue background by adding the .blue class.

<head>
<style scoped>
.demo {
width: 100px;
height: 100px;
}
.blue {
background-color: blue;
}
</style>
</head>
<div class="demo" :class="color"></div><script>
new Vue({
el: "#app",
data: {
color: "blue",
},
});
</script>

In-line Styling:

<div class="demo" :style="{backgroundColor: color}"></div>

Styling by Class:

<div :class="[{'blue': true}, {'dimensions': true}]"></div>

Nesting: Elements nested inside of another element will have access to the variables declared in the parent.

<div v-for="(ingredient, index) in ingredients">
<h1>{{ingredient}}</h1>
<p>{{index}}</p>
</div>

Accessing Instance Properties From Outside of the Instance: Vue proxies the properties inside of the instance. Therefore, to access properties inside of the instance, you can access them directly. What does that mean? Let me demonstrate with a quick example: if you are outside of your Vue instance and you want to access the “title” property in the data object, you do no need to use yourVueInstance.data.title. Instead, you would use yourVueInstance.title. Note, you cannot set Vue properties from outside of the instance.

You can also access direct properties of the Vue instance with .$ (i.e. .$data, .$refs, .$el). You can define life cycle methods with .$.

<script>
const vm1 = new Vue({
el: "#app1",
data: {
title: "The first VueJS Instance",
},
});
setTimeout(function() {
vm1.title = "Changed by Timer";
}, 3000);
</script>

Refs: You can use the ref attribute on any HTML tag to access said element in your script (i.e. methods). See below.

<h1 ref="myTitle">Title</h1><script>
const vm1 = new Vue({
el: "#app1",
});
console.log(vm1.$refs); // {myTitle: h1}
console.log(vm1.$refs.myTitle.innerText); //Title
</script>

You can set the text inside the element using $refs.myTitle.innerText

<h1 ref="myTitle">Title</h1>
<button @click="show">Change Title</button>
<script>
const vm1 = new Vue({
el: "#app1",
methods: {
show: function() {
this.$refs.myTitle.innerText = "New Title";
},
},
});
</script>

.$mount(): This method mimics the “el” property in the Vue instance. You can apply the Vue instance to a element by passing the CSS selector into .$mount().

<div id="app">
</div>
<script>
const vm1 = new Vue({
data: {
title: "Title from Data",
},
methods: {
show: function() {
console.log('hello');
},
},
});
vm1.$mount(#app)
</script>

Creating a Component: You cannot reuse a Vue instance. However, you can create a reusable component containing HTML using Vue.component(). This will register the component globally. The component you create will become an HTML element (in the example below, we created a new HTML element called <helloelement>. Make sure you create the component before you create the instance. Also, do not use camel case.

<body>
<div id="app">
<helloelement></helloelement>
<helloelement></helloelement>
<helloelement></helloelement>
</div>
<script>
Vue.component("helloelement", {
template: "<h1>Hello</h1>",
});
new Vue({
el: "#app"
});
</script>
</body>

Adding properties to a component: You can utilize the same properties in a component as a Vue instance. However, the data property needs to be returned from a function. All other methods can be defined/accessed the same way as a Vue instance.

<div id="app">
<my-component></my-component>
<my-component></my-component>
</div>
<script>
Vue.component("my-component", {
data: function() {
return {
status: "Critical",
};
},
methods: {
changeStatus: function() {
this.status = "Normal";
},
},
template: "<p>Server Status: {{status}} <button @click='changeStatus'>Change</button> </p> ",
});
new Vue({
el: "#app",
});
</script>

Gotcha: In the code above, we created a component called <my-component>. We display <my-component> twice. If we click on the button of one of the components, it will change the status on only one component.

In the code below, we create dataObject outside of the Vue instance that is exactly the same as the object that we returned from the function in the data object in the example above. Then, we return dataObject from the function.

If we click our “changeStatus” button, what will happen? In dataObject, status will be updated to “Normal.” As such, even though we only wanted to change the status property in one component, the status property will be changed in both components because both components share the same reference to dataObject.

<div id="app">
<my-component></my-component>
<my-component></my-component>
</div>
<script>
const dataObject = {
status: "Critical",
};
Vue.component("my-component", {
data: function() {
return dataObject;
},
methods: {
changeStatus: function() {
this.status = "Normal";
},
},
template: "<p>Server Status: {{status}} <button @click='changeStatus'>Change</button> </p> ",
});
new Vue({
el: "#app",
});
</script>

Attribute Fallthrough on Custom Components: Attributes (i.e. @click.native) set on custom components are applied to the native HTML elements inside of the components by using @click.native.

Importing Components Locally: To use a component, import it. Then, pick a name (base-card) for that component. Set the component’s name (base-card) to the imported name (BaseCard). Now, you can insert the imported component as an HTML tag in your component.

<template>
<base-card>
</base-card>

</template>
<script>
import BaseCard from "../UI/BaseCard";
export default {
components: {
base-card: BaseCard
},

};
</script>

Life Cycle Methods: Declare the life cycle methods directly in the Vue instance. To access them, use $yourLifeCycleMethod. See example below shows all of the life cycle methods.

  • mounted: You can insert logic in the mounted() life cycle method to automatically load information when the page loads.
<script>
const vm1 = new Vue({
el: "#app1",
data: {
title: "The first VueJS Instance",
},
beforeCreate: function() {
console.log("beforeCreate()");
},
created: function() {
console.log("created()");
},
beforeMount: function() {
console.log("beforeMount()");
},
mounted: function() {
console.log("mounted()");
},
beforeUpdate: function() {
console.log("beforeUpdate()");
},
updated: function() {
console.log("updated()");
},
beforeDestroy: function() {
console.log("beforeDestroy()");
},
destroyed: function() {
console.log("destroyed()");
},
methods: {
destroy: function() {
this.$destroy();
},
},
});
</script>

SVG’s in Vue: SVG’s are more dynamic than png’s because you can change the color. Wrap your <path> with <svg> tags. Then give the <svg> element a class. Then you specify your color using the “fill” property. Make sure you don’t have a <defs> element inside your <svg> tags.

<svg class="red" xmlns="http://www.w3.org/2000/svg" width="30" height="23.329" viewBox="0 0 30 23.329">
<path class="a" d="M14.587,38.1l9.6,7.908v8.535a.833.833,0,0,0,.833.833l5.836-..."/>
</svg>
//CSS
.red {
fill: red;
}

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store