The Comparison of The Champions: Angular vs Vue
Software Development
Oliwia Oremek
2021-12-22

The Comparison of The Champions: Angular vs Vue

Currently, there are a few frontend frameworks used commonly and constantly developed by its creators, each slightly different than the other. And yet, they may have something in common. Here is a comparison based on the development process – Google’s Angular vs. open-source Vue.js:

Setting up a project

The fastest way to kick off a project is by using the CLI provided by the frameworks’ authors. Both come with pretty good service; however, there are few differences i.e., Vue comes with more options, therefore, you can tailor a project to your needs from the start right. You can choose the Vue version, whether you need to use routing. Typescript, CSS preprocessors or set up a linter right ahead. Also, it lets you decide if you want to set up tests (unit or E2E).

Vue CLI

Angular comes with a generator which allows you to create components, services, interfaces and directives right from the console, which from my experience is very handy as there is no need to manually set up folders, files and redundant code by hand, especially when you use i.e., MVC pattern. Typescript comes out of the box with Angular and kind of pressures you to use it. If you haven’t done it yet, here is a handy introduction why you should try it out - you can check it out here.

At the start, Angular’s CLI asks you only about routing or preferred CSS preprocessors which, in comparison to Vue, doesn’t leave you much space to decide about the structure and style of your application. But if you are going to follow the convention it asks you to use, the CLI is going to lead you all the way.

Angular CLI

Project structure

Vue uses SFC (Single File Components) which makes it quite simple for a new developer to start using a framework and find their feet in the code.

Directives

Vue also comes out of the box with directives such as `v-if, v-for`, which is very intuitive to use as it is almost a copy of the Angular ones. Vue uses the same convention for two-way data binding (just by prefixing it with, i.e., v- in `v-model`) and adding the @/v-on indicating that we are reacting to something. Angular separates this by indicating which way we are going by using parentheses for event binding and square brackets for property binding, i.e. ,`(change), [ngStyle], [(ngModel)]`.

In Vue, the structure itself is simple, there is no need to make separate files for stylesheets and logic, so it’s all organized and approachable. Of course, Vue comes with a style guide where you can find recommended rules to follow when creating a project; however, there are only a few that are mandatory. 

Events

I this case, Vue comes again with a more handy solution; namely, to emit an event from the child component to its parent all you need to do is (using Vue 3 Composition API ) take a method from the context object in the setup and simply emit whatever you need at the moment:

setup(props, { emit }) { const componentMethodYouWantToUseSomewhere = () => { emit(‘customNameOfYourEvent’, dataYouWantToPass); } }

You can also do it directly in the template as a response to some other event.

In Angular, you need to first define an EventEmitter as follows:

@Output() customNameForYourEmitter = new EventEmitter<Data>();

Then you need to call an emit method on the EventEmitter:

this.customNameForYourEmitter.emit(this.theDataYouWantToPass);

Slots/content projection

In both frameworks, you can easily move the content (single as well as multiple) from the parent component to its child just by adding additional html inside the child tags, with slight differences:

Vue:

`<slot name="header"></slot>`

```

Angular:

Default:
    <ng-content></ng-content>

Named slot:
    <ng-content select="[yourName]"></ng-content>
<p yourName>
   This is a named slot
  </p>
  <p>This is a default slot</p>

However, if you want to conditionally render some parts of your application, Vue is more intuitive than Angular and lets you do it faster by adding the v-if directive to your <template> tag, which allows you to render only the parts that are currently needed.

<template v-if="someConditionToBeMet”>
  <!-- render this part if condition is met -->
</template>
<template v-else>
  <!-- render this if first condition isn’t met -->
</template>

While the ng-content is always rendered, you need to use in this case the ng-template, and later create your own custom directive:

<div *ngIf="conditionToBeMet" [id]="contentId">
    <ng-container [ngTemplateOutlet]="content.templateRef"></ng-container>
</div>
@Directive({
  selector: '[customDirectiveName]'
})
export class CustomDirective {
  constructor(public templateRef: TemplateRef<unknown>) {}
}

and because of the name you give to your ng-template attribute, Angular will know what should be rendered:

<ng-template customDirectiveName>
  <!-- content goes here -->
</ng-template>

Also, within the component, you want to project your template to be used in the @ContentChild to get the proper template:

@ContentChild(CustomDirective) content!: CustomDirective;

Service vs store

Angular at its core encourages you to use the MVC design pattern where you can use services for the model. Because of that, you need to learn the dependency injection pattern to freely operate data in your application. It lets you separate side effects of your, i.e., API calls and use the same logic across the whole project by injecting the parts you need at the moment, which also makes it a modular approach.

Angular also comes with the Ngrx/store framework based on the Redux pattern in case you want to use a more reactive approach with RxJs observables. It comes with Actions that are used for dispatching unique events from components and/or services, Effects that handle side effects or async actions you want to perform and Reducers that mutate your state.

In Vue, the popular approach is to use the Vuex library for state management which also comes with tools like Actions, Mutations and Getters, just like Ngrx/store, to help you manage and organize the state of your application. You can modularize it by setting different stores for your views, i.e., a user store or a cart store, but it can lead to name-spacing problems, unless you use the namespaced: true property in your store declaration.

Here is a comparison of services-based approach and the Vuex one when the task is to fetch some product data for your shop:

@Injectable() // decorator to indicate we want to use it in DI later on
export class ProductsService {
  private products: Product[] = [];

  constructor(private backend: BackendService) { }

  getProducts() {
    this.backend.getAll(Product).then( (products: Product[]) => {
      //do whatever you like with your products 
    });
    return this.products;
  }
}

Then, in the component, we inject our service to be used: constructor(private service: HeroService) { }

In Vue, we simple dispatch an action that makes a backend call for us:

store.dispatch(getAllProducts)

and in the actions.ts file we define an action:

actions: {
getAllProducts ({ commit }){
    commit(‘setProducts’, await getProducts();); // fetch data and put the results in the store
}}

Fetching data

With Vue, you can use Axios/Fetch or whatever library you want to use, it is really straightforward – you just handle asynchronous calls with promises or whatever approach suits you best.

try {
http.get(‘https://url.to.get.data’)
    .then(res => res.json())
    .then(data => console.log(do whatever is needed’))
} catch (e) {
    //handle error
}

Angular comes with the HttpClient library that uses observables leading you to another perk – to use it properly and/or manipulate data, you need to learn RxJs. Again, it can be quite overwhelming to get fluent and feel familiar with this abstract construct at the very beginning.

You can use Axios if that’s what you want to do but as the Axios GitHub page says: ‘Axios is heavily inspired by the $http service provided in Angular

private getAllItems(): void {
this.http
.get<Item>(‘https://url.to.fetch.data’)

.pipe(
pluck(‘results’),
tap(console.log(do whatever side effect you want to use here’)
catchError((error) => {
        //handle error
})
)
.subscribe((result: ResultType[])
    //final operation on given output
)
}

Summing up

VueAngular
Does not push you to follow very strict rulesRequires using Typescript, class-based components/services
Flat learning curve, easy to start withHigh learning curve (Typescript, RxJs, Dependency Injection)
A lot of things to configure during project setupNot much to set up front but it lets you generate project structure through console
Community-driven framework based on both Angular and ReactCreated and maintained by Google
Not much is included, need to install external librariesState management, HttpClient included in the framework
Get free code review

Read more:

JavaScript Is Totally Dead. Some Dude on the Internet

Deploy GraphQL/MongoDB API Using Netlify Functions

How to Kill a Project with Bad Coding Practises