Creating Single Page Application using Vue.js (Part 1)

Javascript is increasingly popular for web-based application development not only on the client side (browser), but also as server-side language, which is then strengthened by the latest ECMAScript standards such as ECMAScript6 (ES6) or also called ECMAScript 2015 (ES2015). For more details about this standard please read the very useful explanation from Luke Hoban. I remembered about decade ago, Javascript is the most annoying client-side programming language because of the non-standard implementation in every browser. Often my web application runs smoothly in Interner Explorer 5 or 6, but not running at all with Mozilla, Netscape or Firefox and it also apply the opposite, Microsoft tends to make their own implementation of Javascript. Along with the increasingly widespread use of web-based application, Javascript is increasingly being used to create responsive and "reactive" web applications. The term "Reactive" becoming some kind of "mantra" in the current web development, which refers to the ability to "reactivate" the DOM (HTML Document Object Model) / HTML tag so that when the value is changed in the Javascript code it will automatically change the HTML tag, and vice versa if we pass changes in the HTML, then the changes will be reflected in the Javascript code. Some Javascript frameworks / libraries that allow us to build these reactive web applications include: AngularJS (not Angular), Backbone.js, Ember, React, Riot, Polymer, and in this article we will discuss Vue.js, which declares itself as "The Progressive JavaScript Framework" (all Javascript frameworks claims to be better compared to any other framework 😬).
Reactivity
To see an example of "reactivity" with Vue.js, lets we create an HTML file named index.html and enter the following code:
index.html
<!doctype html>
<html lang="en">
<head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<link rel="stylesheet" href="assets/css/bootstrap.min.css">
<script src="assets/js/vue.min.js"></script>
<title>Reactivity Example</title>
</head>
<body>
<div id="spa">
<div class="jumbotron jumbotron-fluid p-3">
<h1 class="display-4 text-center">{{ reactive_text?reactive_text:'Hmmmm...' }}</h1>
<hr class="my-4"/>
<p class="lead text-center"><input type="text" class="form-control" v-model="reactive_text"/></p>
</div>
<script>
var spa = new Vue({
el: '#spa',
data: {
reactive_text: 'This is reactive text!'
}
})
</script>
</body>
</html>
Open index.html file with your favorit browser and we will see something like this:

Single Page Application
With the emergence of Javascript reactive libraries such as Vue.js, it encourages the web application development model called "Single Page Application (SPA)", where all "views" are built using only an HTML file which then loads the component view / other modules by injecting (or rendering) dynamically with Javascript. Using SPA approach, the server-side apps no longer have to send back full HTML responses, just the data in JSON format (using AJAX) for example, which will be then reacted by Vue.js, any changes on the client side will trigger changes to the server, and vice-versa and in the end the data communication between client and server becoming more faster because of small data size. Let's look at a simple example using Vue.js below:
index.html
<!doctype html>
<html lang="en">
<head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<link rel="stylesheet" href="assets/css/bootstrap.min.css">
<script src="assets/js/vue.min.js"></script>
<script src="assets/js/vue-router.min.js"></script>
<title>Single Page Application Vue.js</title>
</head>
<body>
<div id="spa"><!-- root element of SPA application -->
<!-- Main navigation of SPA application
please note the tag "router-link" which is special tag to make hyperlink to Vue's router -->
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
<router-link class="navbar-brand" to="/">SPA Vue.js</router-link>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navigasi"
aria-controls="navigasi" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navigasi">
<ul class="navbar-nav mr-auto">
<li class="nav-item">
<router-link class="nav-link" to="/">Home</router-link>
</li>
<li class="nav-item">
<router-link class="nav-link" to="/news">News</router-link>
</li>
</ul>
</div>
</nav>
<!-- "router-link" above will render each of its view inside "router-view" tag -->
<div id="main-content">
<router-view></router-view>
</div>
</div>
<!-- view template for "Home" component -->
<script type="text/x-template" id="home">
<div class="jumbotron jumbotron-fluid"><h1 class="display-4 text-center">{{ title }}</h1>
<hr class="my-4"/>
<p class="lead text-center">{{ content }}</p>
</script>
<!-- view template for "News" component -->
<script type="text/x-template" id="news">
<div>
<p class="p-1"><input type="text" class="form-control" v-model="keywords"
v-on:keyup="search"
placeholder="Put some keywords"></p>
<div v-if="news_filtered.length>0">
<div class="news p-2" v-for="n in news_filtered">
<p class="h4">{{ n.title }}</p>
<p class="lead">{{ n.content }}</p>
<hr/>
</div>
</div>
<div v-else>
<div class="news p-2" v-for="n in news">
<p class="h4">{{ n.title }}</p>
<p class="lead">{{ n.content }}</p>
<hr/>
</div>
</div>
</div>
</script>
<!-- The javascript code run Vue instance -->
<script src="assets/js/app.js"></script>
</body>
</html>
assets/js/app.js
// 1. Define Vue components
// "Home" component will display application homepage
const Home = Vue.extend({
template: '#home',
data: function() {
return {
title: 'Welcome to Single Page Application',
content: 'Vue.js enable web developer to create dynamic web application which is light and fast.'
}
}
});
// "News" component will display news/article data
var news_data = {
keywords: '',
news: [
{title: 'Lorem Ipsum', content: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur feugiat, eros quis semper dignissim, libero erat semper ante, non porttitor sem metus a neque.'},
{title: 'In Vehicula Vulputate', content: 'In vehicula vulputate eros vitae porttitor. Praesent commodo accumsan semper. Proin eu tellus purus, eu malesuada sapien.'},
{title: 'Aliquam Laoreet Gravida Erat', content: 'Aliquam laoreet gravida erat, in hendrerit arcu lobortis id. Cras libero augue, aliquam nec sollicitudin id, molestie eu ante.'},
{title: 'Donec Adipiscing', content: 'Donec adipiscing, diam eget tempor volutpat, odio justo molestie dolor, vitae sodales felis risus a mi.'},
{title: 'Praesent Mollis', content: 'Praesent mollis placerat mi ut accumsan. Vivamus ultricies lobortis risus, quis venenatis ligula elementum id.'},
],
news_filtered: []
};
const News = Vue.extend({
template: '#news',
data: function() {
return news_data;
},
methods: {
search: function() {
var searched_keyword = new RegExp(this.keywords, 'ig');
if (this.keywords.length > 2) {
this.news_filtered = this.news.filter(el => el.title.search(searched_keyword)>-1);
} else {
this.news_filtered = [];
}
}
}
});
// 2. Define routing to component
const routes = [
{ path: '/', component: Home},
{ path: '/news', component: News }
]
// 3. Create Vue Router instance
const router = new VueRouter({ routes })
// 4. Mount/attach "router" instance to Vue app
const spa = new Vue({ router }).$mount('#spa');
I will try to explain some important points to notes here, especially for you who just get to know Vue:
- Please note that for this SPA example, I'm using the Bootstrap version 4.0 framework, so make sure that you have also downloaded and installed Bootstrap 4.0. In this paper all my CSS files
are put in the
assets/css/directory and all the Javascript files I put in theassets/js/directory; - To use Vue, we must have included the Vue library file in the
headpart of the HTML file. Because we build the SPA interface, we also need the Vue Router that will enable components routing. Download the Vue.js library here and Vue Router here. Or if you are the lazy type person just use the CDN version for each library respectively hehehe; - Notice that there is a custom <router-link class="nav-link" to="/">Home</ router-link> tag that will automatically be recognized by the Vue Router and will be transformed to anchor tag and create internal link to route destination designated by the attribute "to". All hyperlinks heading to Vue's route must use this custom tag;
- Custom <router-view></router-view> tag serves as a placeholder of the view for each route component;
- We define view or display for each component by using <script type="text/x-template" id="news">. X-Templates is one of the template types supported by Vue, and IMO is the most secure and easy to use for small to medium-sized application;
- Code in a form like {{title}}, {{content}} is called Mustache which is a placeholder for data. moustache will be automatically replaced by Vue with the data we assign to the component and it is already reactive;
- Vue also has directive attributes, which we use in this example are
v-bind, v-if, v-else, v-for, v-modelandv-on. Wev-modelto make the HTML tag reactive with the data model we define in Vue component,v-ifandv-elseallows us to load part of the view under certain conditions,v-forallows us to loop inside view and very useful for displaying data in the form of Javascript's Array or Object, andv-onwe use to associate an HTML tag with "method" which we define in Javascript Vue code; - All Javascript code to run Vue is placed in the
assets/js/app.jsfile and placed at the very bottom of the HTML code; - The
news_dataobject in the Javascript code is static (not dynamic), where in the real SPA application this news data will be retrieved via AJAX from the database on the server-side application; - To create components (in terms of traditional MVC web applications we can assume components are both controllers and models), we use the Vue.extend ({}) syntax;
- Each Vue component is a Javascript object that usually has these properties:
data, methodsand/orcomputed; - The Vue application is run by creating an instance through the Vue constructor which is
const spa = new Vue ({}). After that spa object becoming global object that can be accessed by all components through methods.
If we run the index.html file in the browser we will see our application as follows:

We can see that moving from one page to another takes very quickly, no page loading required, because it doesn't require HTTP requests back to the server. All the page processing/rendering is done on the client side by Vue.js and Vue Router, HTTP requests are only required for data communication in JSON or other plain-text formats, no HTML code response needed and that makes applications faster like a desktop application. In the Part 2 we will see a slightly more complex example involving a news data entry form. Happy coding and trying!
Part 2 nya mana nih? ditunggu..
ReplyDelete