Angular is a popular, fully-fledged JavaScript framework used to build modern web applications. React and VueJS are up-and-coming JavaScript libraries, and are used to build web-interfaces.
In this article, we will contrast AngularJS (v1), Angular 2 and React with VueJS by building a small, single-page sample app.
The article will consider the similarities and differences between Angular, VueJS and React in templating, component definition, directive definition, application design, performance, design flexibility and functionality.
Are you keeping up with new developer technologies? Advance your IT career with our Free Developer magazines covering Angular, React, .NET Core, MVC, Azure and more. Subscribe to this magazine for FREE and download all previous, current and upcoming editions.
Angular vs React vs VueJS – Similarities and Differences
We will begin by building a demo application using AngularJS (the first version of Angular), as AngularJS has served as an inspiration in the design of VueJS. AngularJS remains to be one of the most popular JavaScript frameworks for developing modern web-applications. Released almost seven years ago, the framework is supported by Google, and aims to provide developers with all the necessary tools, along with a strict set of patterns for front-end development.
Editorial Note: The latest version of Angular as of this writing is v4. After AngularJS, Angular 2 was released. There was no v3. Since Angular v2 to v4 is a progressive enhancement, a majority of the changes are non-breaking and almost all the Angular 2 principles and differences discussed in this article, apply to Angular v4 too. Going forward, Angular will not be referred to as Angular 4 or 5 or 6. It is going to be called just “Angular”.
VueJS is an up-and-coming JavaScript library for developing web-interfaces. Released in 2013, VueJS was inspired by AngularJS (v1), and as such borrows the framework’s templating syntax. For example, and as we will see shortly, the syntax for loops, conditionals, model declarations and interpolation all look very similar to that used by AngularJS.
Editorial Note: If you are new to VueJS, read this beginner tutorial http://bit.ly/dnc-vuejs
Vue’s focus is on doing two things well: ease of use and rendering speed.
It excels in both. The library is extremely easy to learn and use, and beats both AngularJS and React when it comes to page rendering. As such, VueJS feels almost like Angular’s fitter little brother as it shares the aspects done well, but at the same time is much lighter, more performant and less opinionated than AngularJS.
However being a library, as opposed to a framework, means that VueJS does not offer the same amount of functionality that AngularJS offers. For example, whilst Angular provides things such as a HTTP request service or router, VueJS users will require to rely on third-party code if they wish to avail of such functionalities.
Angular.js vs Vue.js
As VueJS is gaining in popularity, it is important to understand the differences, advantages and disadvantages between VueJS and AngularJS. Therefore this article sets out to explore both VueJS and AngularJS, by building a sample demo application: SurfPics.
The hypothetical SurfPics website will allow surfers to display their various beach and surf videos and photographs. In the first section of this article, we will outline the boilerplate code for this demo application. In the subsequent two sections we will then walk you through the development of the application, using first AngularJS and then VueJS. The similarities between the frameworks should become evident quite quickly.
Once we have established the similarity between the two frameworks, we will contrast VueJS to Angular 2, which deviates slightly from its predecessor (AngularJS). Nonetheless, here too, similarities are apparent.
Last but not least, we will discuss the advantages, disadvantages, differences and similarities between a performant alternative to VueJS and AngularJS: React.
React was developed by Facebook. Similar to VueJS, its objective is to build performant web-interfaces.
Figure 1: Our demo page - built using Materialize.
Demo application - Preparation
Before we can start diving into VueJS and AngularJS, we must lay the groundwork for our demo application.
To begin with, create a directory called src, containing three sub-directories: angular, angular2 and vue. These directories will contain our AngularJS and VueJS application respectively.
Inside both the angular and vue folder, create the following three, empty, files:
- index.html
- app.js
- app.css
Add the following styles to app.css:
#app {
min-height: 460px;
}
.text-muted {
color: lightgrey;
}
.search-box {
margin-left: 1em;
margin-top: -1em;
}
The above CSS rules are fairly self-explanatory: they will set the colors, margins and minimum height for our application.
As this article does not concern itself with the intricacies of markup and CSS styles, you can safely ignore these boilerplate rules once you have added them to the application’s CSS file.
The index.html file should contain the skeleton for our sample application:
<!DOCTYPE html>
<html>
<head>
<title>SurfPics</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.98.0/css/materialize.min.css">
<link href="http://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<link rel="stylesheet" href="app.css">
</head>
<body>
<nav>
<div class="nav-wrapper">
<a href="#" class="brand-logo">SurfPics</a>
<ul id="nav-mobile" class="right hide-on-med-and-down">
<li class="active"><a href="index.html">Home</a></li>
<li><a href="foo.html">Foo</a></li>
<li><a href="bar.html">Bar</a></li>
</ul>
</div>
</nav>
<div id="app">
<!-- App content goes here -->
</div>
<footer class="page-footer">
<div class="footer-copyright">
<div class="container">
© 2017 Copyright SurfPics
</div>
</div>
</footer>
<script src="app.js"></script>
<script type="text/javascript" src="https://code.jquery.com/jquery-2.1.1.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.98.0/js/materialize.min.js"></script>
</body>
</html>
Again, the above markup is very straightforward and self-explanatory: We created a page containing a navbar and a footer, and included the relevant dependencies (jQuery and materialize).
As per best-practices, JavaScript files are loaded at the bottom of the page (as opposed to the top, which hampers download parallelization and may give the impression of poor page load times).
Note the third party dependency aside from jQuery: Materialize.
Materialize is “a modern responsive front-end framework based on Material Design” (http://materializecss.com/), and we will be using it to style our demo application (“Material Design” refers to a set of visual design guidelines created by Google). The framework provides some slick styling, and is essentially the Bootstrap equivalent for Material Design lovers.
Building a page using AngularJS 1.6
The demo application that we will be building is going to be very simple and will consist of one page, displaying a set of available photographs (see figure 1). Each photograph will be accompanied by a short description and a title. The photograph, title and description will be presented in the form of a card.
In addition to displaying a set of photographs, we will be providing a search bar above the photographs, which, in theory, will allow users to search for photographs whose title or description contains a certain string.
Although we will not be implementing the search functionality itself, we will be implementing a “searching” message to indicate to the user that the search is in progress as the search term is being entered.
Let’s begin by first including AngularJS 1.6.1 in our page: Place the following line above the script tag for app.js:
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.1/angular.min.js"></script>
Next, we define our application controller. Open angular/app.js and insert the following code.
angular.module('app', [])
.controller('AppController', function() {
var app = this;
});
Inside this application controller, we will be hard-coding our set card information:
angular.module('app', [])
.controller('AppController', function() {
var app = this;
this.cards = [
{
title: 'Sunrise with palm trees',
description: 'Lorem ipsum dolor sit amet, aliqua’,
img_src: "img/1.jpg"
},
{
title: 'Sunrise',
description: 'Lorem ipsum dolor sit amet, consectetur aliqua',
img_src: "img/2.jpg"
},
{
title: 'Copacabana sunrise',
description: 'Lorem ipsum dolor sit ut labore et dolore magna aliqua',
img_src: "img/3.jpg"
},
{
title: 'Surfer',
description: 'Lorem ipsum dolor sit ame magna aliqua',
img_src: "img/4.png"
}
];
});
To display the cards, first define the controller: add ng-controller="AppController as ctrl” to the div where id=“app”.
Next add the following markup inside this application div:
<div class="row">
<div class="col s12 m3" ng-repeat="card in ctrl.cards">
<div class="card">
<div class="card-image">
<img ng-src="{{card.img_src}}">
<span class="card-title">{{card.title}}</span>
<a class="btn-floating halfway-fab waves-effect waves-light red”>
<i class=“material-icons">add</i>
</a>
</div>
<div class="card-content">
<p>{{card.description}}</p>
</div>
</div>
</div>
</div>
The markup itself is fairly self-explanatory: we create one row, containing 4 columns. Each column contains one card. Specifically, we iterate over the cards contained in the controller using ng-repeat="card in ctrl.cards”. For each card, we interpolate its contents using the expression {{card.property}}, where property is the card property that we wish to access.
The various classes used in the sample code above are defined by materialize, and served as mere decoration.
Next, we are going to define the search bar.
Insert the following markup above the row containing the photographs:
<div class="row">
<form class="col s12">
<div class="row">
<div class="input-field col s6">
<i class="material-icons prefix text-muted">search</i>
<input ng-change="ctrl.search()" id="icon_prefix" type="text" class="validate" ng-model="ctrl.search_term">
<label for="icon_prefix">Search term</label>
</div>
</div>
<div ng-if="ctrl.search_term" class="row text-muted" class="search-box">
<i class="material-icons search">hourglass_empty</i> {{ctrl.message}}
</div>
</form>
</div>
Once again, the markup should be self-explanatory: we add a row containing an input box.
By using ng-change, we ensure that the controller’s search function is called whenever the input changes. Using ng-if we conditionally display an hourglass icon along with a message (see figure 2 below) if a search term exists (i.e. if the controller’s search_term property is truthy).
The search input is bound to search_term property of our controller using ng-model.
The search function itself is defined inside the controller as follows:
this.search = function () {
app.message = 'Searching for ' + app.search_term + '...';
};
And that’s it - we now have a basic page that:
- Dynamically generates rows using a loop and interpolates the relevant data
- Binds the data of an input
- Conditionally displays a search message
Figure 2: An hour-glass icon along with a search message appears once the search input contains text.
Building a page using VueJS
By building a VueJS equivalent of our AngularJS demo page, we will see that, upon first glance, VueJS seems like a simplified clone of AngularJS. Its directives carry similar names and the VueJS app itself requires no bootstrapping.
We begin building our demo app by including VueJS as one of our dependencies.
Open vue/index.html, and insert the following line above the script tag for app.js:
<script src="https://unpkg.com/vue/dist/VueJS"></script>
Next, we define our VueJS instance in app.js as follows:
var app = new Vue({
el: '#app'
});
Note how little overhead is required to create this instance, and we are not forced to use the concepts of modules and controllers; instead, we simply create a Vue object that targets our application div (i.e. the div with id=“app”).
Targeting our application div means that this Vue instance is available anywhere within the application div.
To define our cards (or any other data), we must use the data property. We will also initialise message to an empty string and search_term to null:
var app = new Vue({
el: '#app',
data: {
message: '',
search_term: null,
cards: [
{
title: 'Sunrise with palm trees',
description: 'Lorem ipsum dolor sit amet, consectetur',
img_src: "img/1.jpg"
},
{
title: 'Sunrise',
description: 'Lorem ipsum dolor sit amet, consectetur',
img_src: "img/2.jpg"
},
{
title: 'Copacabana sunrise',
description: 'Lorem ipsum dolor sit amet, consectetur',
img_src: "img/3.jpg"
},
{
title: 'Surfer',
description: 'Lorem ipsum dolor sit amet, consectetur',
img_src: "img/4.png"
}
]
}
});
Last but not least, we will define our search function by using the methods property:
methods: {
search: function () {
this.message = 'Searching for ' + this.search_term + '...';
}
}
Now it is time to update our template.
As we will see, templates in AngularJS and VueJS look almost identical: we will be replacing ng-model with v-model, ng-if with v-if, ng-repeat with v-for and ng-bind with v-on:change=“search" (table 1 below lists the full set of templating differences between AngularJS and VueJS).
Table 1: Templating differences between AngularJS 1 and VueJS
Specifically, we will replace:
<div class="col s12 m3" ng-repeat="card in ctrl.cards">
with:
<div class="col s12 m3" v-for="card in cards">
Next, we replace:
<img src="{{card.img_src}}">
with:
<img v-bind:src=“card.img_src">
And replace:
<input ng-change="ctrl.search()" id="icon_prefix" type="text" class="validate" ng-model=“ctrl.search_term">
with:
<input v-on:change="search" id="icon_prefix" type="text" class="validate" v-model=“search_term">
Last but not least, we replace:
<div ng-if="ctrl.search_term" class="row text-muted" class="search-box">
<i class="material-icons search">hourglass_empty</i> {{ctrl.message}}
</div>
with:
<div v-if="search_term" class="row text-muted" class="search-box">
<i class="material-icons search">hourglass_empty</i> {{message}}
</div>
And that’s it! Pronto!
We now have a fully functioning VueJS version of our AngularJS demo app. In summary, here is the complete template:
<!DOCTYPE html>
<html>
<head>
<title>SurfPics</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.98.0/css/materialize.min.css">
<link href="http://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<link rel="stylesheet" href="app.css">
</head>
<body>
<nav>
<div class="nav-wrapper">
<a href="#" class="brand-logo">SurfPics</a>
<ul id="nav-mobile" class="right hide-on-med-and-down">
<li class="active"><a href="index.html">Home</a></li>
<li><a href="foo.html">Foo</a></li>
<li><a href="bar.html">Bar</a></li>
</ul>
</div>
</nav>
<div id="app">
<div class="row">
<form class="col s12">
<div class="row">
<div class="input-field col s6">
<i class="material-icons prefix text-muted">search</i>
<input v-on:change="search" id="icon_prefix" type="text" class="validate" v-model="search_term">
<label for="icon_prefix">Search term</label>
</div>
</div>
<div v-if="search_term" class="row text-muted" class="search-box">
<i class="material-icons search">hourglass_empty</i> {{message}}
</div>
</form>
</div>
<div class="row">
<div class="col s12 m3" v-for="card in cards">
<div class="card">
<div class="card-image">
<img v-bind:src="card.img_src">
<span class="card-title">{{card.title}}</span>
<a class="btn-floating halfway-fab waves-effect waves-light red"><i class="material-icons">add</i></a>
</div>
<div class="card-content">
<p v-sp-grey>{{card.description}}</p>
</div>
</div>
</div>
</div>
</div>
<footer class="page-footer">
<div class="footer-copyright">
<div class="container">
© 2017 Copyright SurfPics
</div>
</div>
</footer>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script src="app.js"></script>
<script type="text/javascript" src="https://code.jquery.com/jquery-2.1.1.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.98.0/js/materialize.min.js"></script>
</body>
</html>
Building a page using Angular (v2)
Before we can begin building an Angular 2 application, we must first setup our development environment. As per the official Angular2 documentation:
“The QuickStart seed contains the same application as the QuickStart playground. But its true purpose is to provide a solid foundation for local development. Consequently, there are many more files in the project folder on your machine, most of which you can learn about later.”
To install the QuickStart seed, navigate to https://angular.io/docs/ts/latest/guide/setup.html#download and download the QuickStart seed. Extract the downloaded archive into the angular2 directory that we created previously. Copy the image folder (img) into quickstart-master/src. From your command line, execute the following three commands:
cd quickstart-master
npm install
npm start
A new browser window should open: http://localhost:3000/
Inside quickstart-master/src, update index.html to the following:
<!DOCTYPE html>
<html>
<head>
<title>SurfPics</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.98.0/css/materialize.min.css">
<link href="http://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<link rel="stylesheet" href="app.css">
<base href="/">
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="styles.css">
<!-- Polyfill(s) for older browsers -->
<script src="node_modules/core-js/client/shim.min.js"></script>
<script src="node_modules/zone.js/dist/zone.js"></script>
<script src="node_modules/systemjs/dist/system.src.js"></script>
<script src="systemjs.config.js"></script>
<script>
System.import('main.js').catch(function(err){ console.error(err); });
</script>
</head>
<body>
<nav>
<div class="nav-wrapper">
<a href="#" class="brand-logo">SurfPics</a>
<ul id="nav-mobile" class="right hide-on-med-and-down">
<li class="active"><a href="index.html">Home</a></li>
<li><a href="foo.html">Foo</a></li>
<li><a href="bar.html">Bar</a></li>
</ul>
</div>
</nav>
<my-app>Loading AppComponent content here ...</my-app>
<footer class="page-footer">
<div class="footer-copyright">
<div class="container">
© 2017 Copyright SurfPics
</div>
</div>
</footer>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script src="app.js"></script>
<script type="text/javascript" src="https://code.jquery.com/jquery-2.1.1.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.98.0/js/materialize.min.js"></script>
</body>
</html>
As we already covered the markup in the previous sections, we won’t iterate over the description here. However, take note of the following line;
<my-app>Loading AppComponent content here …</my-app>
This references the root component that will ideally consist of sets of nested components. As our application is simple, we won’t be developing a tree of components, but instead just work with the application root component (called “my-app”).
To this end, update quickstart-master/src/app/app.component.ts to contain the following:
import { Component } from '@angular/core';
@Component({
selector: 'my-app',
template: `
<div class="row">
<form class="col s12">
<div class="row">
<div class="input-field col s6">
<i class="material-icons prefix text-muted">search</i>
<input (keyup)="search($event)" id="icon_prefix" type="text" class="validate" v-model="search_term">
<label for="icon_prefix">Search term</label>
</div>
</div>
<div v-if="search_term" class="row text-muted" class="search-box">
<i class="material-icons search">hourglass_empty</i> {{message}}
</div>
</form>
</div>
<div class="row">
<div class="col s12 m3" *ngFor="let card of cards">
<div class="card">
<div class="card-image">
<img src="{{card.img_src}}">
<span class="card-title">{{card.title}}</span>
<a class="btn-floating halfway-fab waves-effect waves-light red"><i class="material-icons">add</i></a>
</div>
<div class="card-content">
<p>{{card.description}}</p>
</div>
</div>
</div>
</div>
`,
})
export class AppComponent {
message = '';
search_term: null;
cards = [
{
title: 'Sunrise with palm trees',
description: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua',
img_src: "img/1.jpg"
},
{
title: 'Sunrise',
description: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua',
img_src: "img/2.jpg"
},
{
title: 'Copacabana sunrise',
description: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua',
img_src: "img/3.jpg"
},
{
title: 'Surfer',
description: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua',
img_src: "img/4.png"
}
];
search(event: any) {
this.message = 'Searching for ' + event.target.value + '...';
}
}
Having developed both the AngularJS 1 app, and the VueJS application, the above code should look familiar, even if is written in TypeScript: we define our search method and the apps data.
The markup for the component goes into the component’s template. By examining the markup, we see that there is no difference in the actual structure of the application - only in the naming of the default directives (more on this later).
In summary, here’s the complete Angular template:
<!DOCTYPE html>
<html>
<head>
<title>SurfPics</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.98.0/css/materialize.min.css">
<link href="http://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<link rel="stylesheet" href="app.css">
<base href="/">
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="styles.css">
<!-- Polyfill(s) for older browsers -->
<script src="node_modules/core-js/client/shim.min.js"></script>
<script src="node_modules/zone.js/dist/zone.js"></script>
<script src="node_modules/systemjs/dist/system.src.js"></script>
<script src="systemjs.config.js"></script>
<script>
System.import('main.js').catch(function(err){ console.error(err); });
</script>
</head>
<body>
<nav>
<div class="nav-wrapper">
<a href="#" class="brand-logo">SurfPics</a>
<ul id="nav-mobile" class="right hide-on-med-and-down">
<li class="active"><a href="index.html">Home</a></li>
<li><a href="foo.html">Foo</a></li>
<li><a href="bar.html">Bar</a></li>
</ul>
</div>
</nav>
<my-app>Loading AppComponent content here ...</my-app>
<footer class="page-footer">
<div class="footer-copyright">
<div class="container">
© 2017 Copyright SurfPics
</div>
</div>
</footer>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script src="app.js"></script>
<script type="text/javascript" src="https://code.jquery.com/jquery-2.1.1.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.98.0/js/materialize.min.js"></script>
</body>
</html>
Table 2: Templating differences between Angular 2 and VueJS
Similarities between AngularJS 1.6 and VueJS
Templating
As we have just seen, the most striking similarity between AngularJS and VueJS is templating.
The syntax is almost identical, with AngularJS using the ng prefix, and VueJS using the v prefix. This similarity is by no means accidental: As noted by the VueJS developers on the official VueJS website: “this [similarity] is because there were a lot of things that Angular got right and these were an inspiration for Vue very early in its development.”
Directives and components
Both AngularJS and VueJS offer components and directives. Whilst AngularJS makes no clear distinction between components and directives, it clearly states that “directives are meant to encapsulate DOM manipulations only, while components are self-contained units that have their own view and data logic”.
In terms of actually creating a directive, we have seen that the AngularJS way is more elaborate.
VueJS on the other hand allows developers to define directives much more concisely. The same holds true for components.
For example, consider that we may want to define a directive that colors an image description text grey. In VueJS, we would first define the directive:
Vue.directive('sp-grey', {
});
where sp-grey is our directive name. We then simply change the color of the bound element as soon as it is inserted into the DOM:
Vue.directive('sp-grey', {
inserted: function (el) {
el.style.color = 'lightgrey';
}
});
The directive can then be used by prepending to v- prefix:
<p v-sp-grey>{{card.description}}</p>
Consider the typical AngularJS equivalent:
angular.module('app').directive('psGrey', function () {
return {
restrict: 'A',
scope: {
text: '@'
},
template: '<span style="color: lightgrey;">{{ text }}</span>'
};
});
We would then use the directive as follows:
<p ps-grey text="{{card.description}}"></p>
Note: In the above, we could alternatively avoid using a template by using link to access the element directly:
angular.module('app').directive('psGrey', function () {
return {
restrict: 'A',
scope: {
},
link: function(scope, element, attrs) {
element.css({'color': 'lightgrey'});
element.text(attrs.text);
}
};
});
Development: Similarities between Angular 2 and VueJS
Templating
Just as with AngularJS 1.6, when it comes to templating, Angular 2 and VueJS are almost identical.
Again, the Angular 2 syntax is almost identical to both VueJS and AngularJS 1.6. Whilst AngularJS 1.6 uses the ng prefix for in-built directives and VueJS uses the v prefix, Angular 2 uses the *ng prefix. So, for example, what is v-for in VueJS, is *ngFor in Angular 2.
Interpolation is identical, and uses the {{ }} form, as is the case for both VueJS and AngularJS 1.6.
Angular 2 uses the concept of template statements in order to bind an action to an event, such as a button.
As per the official Angular 2 documentation: “A template statement responds to an event raised by a binding target such as an element, component, or directive. You'll see template statements in the event binding section, appearing in quotes to the right of the = symbol as in (event)=“statement””.
This means that what is written as <button v-on:click=“perform_task()”>Click Me</button> in VueJS, is expressed as <button (click)=“perform_task()”>Click Me</button> in Angular 2 (see table 2 above).
Directives and components
Aside from TypeScript, the most striking difference between Angular 2 and VueJS, is that Angular 2 is entirely component based. Everything is a component. For example, when creating the SurfPics equivalent in Angular 2, we are really defining a SurfPics component:
@Component({
selector: 'SurfPics'
})
@View({
templateUrl: './index.html'
})
export class AngularComparison {
constructor() {
this.message = '';
this.search_term = null;
// Remainder of app
}
}
Angular 2 components themselves are just directives with a template. Much like VueJS, Angular 2 directives are concisely defined and are used for encapsulating DOM operations. Similar to VueJS, an Angular 2 attribute directive may be used to change the appearance of an element. In Angular 2, our previously introduced ps-grey directive is defined in a similar manner than its VueJS equivalent:
import { Directive, ElementRef, Input } from '@angular/core';
@Directive({ selector: '[psGrey]' })
export class PsGreyDirective {
constructor(el: ElementRef) {
el.nativeElement.style.color = 'lightgrey';
}
}
Development: Similarities between React and VueJS
Templating
React is slightly less intuitive than VueJS.
Instead of using templating, React components are defined using JSX (an XML-like syntax for JavaScript). That is, instead of writing a HTML template, one declares a component class and then calls a special render method to define what it is that is to be rendered:
var hello_world = React.createClass({
render: function() {
return (
<h1>Hello World</h1>
)
}
});
Upon first glance, this looks straightforward, however it can become more complex quickly as a lot of boilerplate code is required to develop more complex applications. For example, to render the list of cards contains the SurfPics beach photos from our previous example, we must:
• define a React component
• declare the cards and then call React.render(), indicating what it is that we want rendered:
// Code placed inside React component definition above
const cards = [
{
title: 'Sunrise with palm trees',
description: 'Lorem ipsum dolor sit amet, consectetur',
img_src: "img/1.jpg"
},
{
title: 'Sunrise',
description: 'Lorem ipsum dolor sit amet, consectetur',
img_src: "img/2.jpg"
},
];
const Iteration = ({ items }) => <div> {items.map(item => <span>{item}</span>)} </div>;
ReactDOM.render(<Iteration items={cards}/>, document.getElementById('cards'));
Then, in our index.html, we would assign the id=“cards” to the element that we want repeated:
<div class="col s12 m3" id=“cards”>
Directives and components
In the React universe, the functionality offered by Angular directives are supported through a set of different types of components. Aside from the default component, it allows developers to define stateless functional components. For example:
const FooButton = ({
name,
callback
}) => (
<button onClick={callback}>Click me, {name}</button>
)
The stateless functional components are possibly the closest analogy to VueJS directives, in that they are commonly used to create purely presentational components. Also known as “dumb components”, these components are not concerned with behavioral logic, but instead just focus on the UI.
Whilst allowing for a more functional-style approach, the lack of templating and directives, and the use of JSX makes React a bit less straight-forward to use than VueJS. For example, in order to express a simple conditional, one would need to develop an entire component:
var hello_world = React.createClass({
render: function() {
if (this.something) {
return (<h1>Hello World</h1>);
} else {
return (<h1>Bye Bye</h1>);
}
}
});
The VueJS equivalent would amount to:
<h1 v-if="something">Hello World</h1>
<h1 v-else>Bye Bye</h1>
Comparing VueJS to other frameworks
Performance
When it comes to rendering performance, VueJS generally outperforms many existing popular frameworks such as AngularJS or React. In fact, VueJS is one of the fastest frameworks to date. For example, the AngularJS 1 equivalent of our demo application, containing one row of data, took almost 14.7 milliseconds longer to render. The significance of this performance difference becomes more evident when increasing our dataset from 1 row to 100 rows of data: VueJS now renders the page in 488.7 milliseconds, whilst AngularJS requires 534.3 milliseconds.
Figure 3 below by Stefan Krause (http://stefankrause.net) gives a more in-depth summary of the various frameworks and performance differences.
Figure 3: Performance benchmark of various JS libraries and frameworks, taken from http://www.stefankrause.net/js-frameworks-benchmark5/webdriver-ts/table.html.
From Stefan Krause’s study, we can see that Vue outperforms most major frameworks, including Angular 2 and React in most types of operations. As noted on the study’s website:
“The benchmarks computes the geometric mean of the ratio between the durations of the benchmarks of the framework to the duration of the fastest framework for that benchmark. A factor X indicates that a frameworks takes on average X times as long as the fastest version (which is usually vanillajs).” (http://www.stefankrause.net/wp/?p=316)
This means that, although VanillaJS and Inferno were usually the most performant, VueJS is much faster at CRUD operations (reading, updating, appending, removing and writing rows to a table). Note: for instructions on running the benchmarks, see https://github.com/krausest/js-framework-benchmark.
Chart 1: Comparative performance in creation of 10,000 rows. Results based on data from Frank Krause’s JavaScript Framework performance benchmarks. (Round 4)
Chart 2: Comparative performance in clearing of 10,000 rows. Results based on data from Frank Krause’s JavaScript Framework performance benchmarks (Round 5).
As can be seen in charts 1 and 2 above, VueJS outperforms Angular and React when it comes to the creation and clearing of elements. The framework is only beaten by VanillaJS. There do however exist operations for which React is faster than Vue. Namely, the appending of elements, partial updates and replacing of elements (see chart 3).
Chart 3: Comparative performance in performing partial updates of 10,000 rows. Results based on data from Frank Krause’s JavaScript Framework performance benchmarks (Round 5).
The VueJS official website boasts similar performance difference between both React and AngularJS. Tested on a “Chrome 52 on a 2014 MacBook Air”, the developers show a significant performance difference when rendering 10,000 list items 100 times:
Table 3: Contrasting the rendering times of 10,000 list items (rendered 100 times) using both VueJS and React. Data taken from the official VueJS website: https://vuejs.org/v2/guide/comparison.html
Memory footprint
Another interesting comparison factor is the memory footprint across the different frameworks.
Krause’s benchmark goes to show that, at roughly 3.6MB, VueJS has a much smaller read memory footprint (after page load) than both React (4.73MB), Angular 1 (5.18MB) and Angular 2 (5.86MB). Although this difference may be small, its significance becomes obvious when considering the memory usage after the addition of 1000 rows: AngularJS v.1.6.1 consumed 14.88MB; at 12.46MB Angular v.2.4.3 consumed only a little less than its predecessor. React v15.4.2 consumed 12.99MB whilst VueJS only required 8.89MB (see chart 4 below).
Chart 4: Comparative memory usage after adding 1000 rows. Results based on data from Frank Krause’s JavaScript Framework performance benchmarks (Round 5).
Although not reflected in the benchmarks above, it is possible to further improve Vue’s rendering times by utilizing its support for server-side rendering.
Server-side rendering means that the server will generate the HTML on-the-fly, reducing the number of requests required to be sent by the client (and hence speeding up loading times). A nice example of an app using server-side rendering in VueJS is the following HackerNews clone: https://github.com/vuejs/vue-hackernews-2.0/
Design flexibility
Much like React, VueJS, is not very “opinionated”.
This means that the library does not dictate how it should be used, and how applications using it should be designed. Whilst other frameworks may force the developer to follow a certain pattern, VueJS does not.
For example, unlike Ember or Angular, VueJS does not force you to use modules or define a controller: instead, one just creates a VueJS object that is configured with the data and methods needed in the template.
Using an opinionated framework can be both advantageous and disadvantageous: it may save developers time by already having something that made design choices for them; or it can become a hurdle as the framework “locks” developers into doing things a specific way.
Functionality
Similar to React, VueJS focuses just on the development of the actual web-interface. Whilst it does this well, it does just that, and nothing more.
Much like React, VueJS does not come with additional tools and features. Anything outside VueJS’ sole purpose must be achieved by either writing the code yourself, or using third-party libraries. The previously discussed alternatives to VueJS, namely AngularJS 1 and 2 (which are complete frameworks), offer full sets of additional functionality.
For example, AngularJS offers services for performing HTTP requests, promise handling, filters for formatting data, routing, a service for cookie handling, or a service wrapper for handling timeouts.
Size
The codebase of VueJS is much smaller and simpler than that of its competitors, such as AngularJS. VueJS 2.1.10 consists of a mere 8569 lines of code. This makes a large difference in terms of actual file size: minified VueJS 2.1.10 is a mere 74KB in size, compared to 168KB for AngularJS 1.6.1 or 520KB for Ember 2.12.0. However, in this comparison, React v.15.4.2 beats VueJS hands-down with 24KB in size.
Chart 5: Comparative file sizes of minified JS.
Learning curve
Another key advantage of VueJS is the fact that it works out of the box. One can load the library using a CDN and get to work immediately.
VueJS works perfectly well without having to use a build system. The same cannot be said for React or Angular 2. The latter, for example, comes with an entire command line interface tool that a developer must use to create, manage, build and deploy the project. The introduction of such tools can increase the learning curve.
Whilst such tools are necessary for large projects, forcing them upon the developer point-blank may be frustrating for some. Furthermore, learning Angular 2 requires first learning TypeScript - this might be a large stepping stone for some.
When it comes to actually learning how to use one of the aforementioned frameworks, there is little difference: the overall design concepts between AngularJS, React and VueJS are all quite similar.
All of the three frameworks/libraries make use of similar concepts, such as components. And whilst the exact definition may vary slightly, the big picture remains the same. If one already understands either React or AngularJS, then grasping the basics behind VueJS will be a matter of a couple of hours.
Conclusion
In this article, we compared VueJS to three other popular JavaScript counterparts: AngularJS and React.
The comparison took into account performance, functionality, design flexibility and the learning curve. In terms of the latter, we discovered that VueJS, React and AngularJS all share very similar concepts, and as such learning how to use VueJS will require minimal effort.
When considering performance, we showed that VueJS outperforms AngularJS, and, in most cases, React.
Lastly, VueJS is similar to React, in that it focuses on a core set of functionality, and as such offers fewer features than Angular. This has the result that VueJS does however provide developers with more design flexibility.
Download the entire source code from GitHub at bit.ly/dncm30-vuejs-vs-ang
This article was technically reviewed by Ravi Kiran.
This article has been editorially reviewed by Suprotim Agarwal.
C# and .NET have been around for a very long time, but their constant growth means there’s always more to learn.
We at DotNetCurry are very excited to announce The Absolutely Awesome Book on C# and .NET. This is a 500 pages concise technical eBook available in PDF, ePub (iPad), and Mobi (Kindle).
Organized around concepts, this Book aims to provide a concise, yet solid foundation in C# and .NET, covering C# 6.0, C# 7.0 and .NET Core, with chapters on the latest .NET Core 3.0, .NET Standard and C# 8.0 (final release) too. Use these concepts to deepen your existing knowledge of C# and .NET, to have a solid grasp of the latest in C# and .NET OR to crack your next .NET Interview.
Click here to Explore the Table of Contents or Download Sample Chapters!
Was this article worth reading? Share it with fellow developers too. Thanks!
Benjamin Jakobus is a senior software engineer based in Rio de Janeiro. He graduated with a BSc in Computer Science from University College Cork and obtained an MSc in Advanced Computing from Imperial College London. For over 10 years he has worked on a wide range of products across Europe, the United States and Brazil. You can connect with him on
LinkedIn.