React, Vue, Angular – A Side-by-Side Comparison of the Three Frontend Giants
/ 8 min read
Table of Contents
Simultaneous Comparison of React, Vue, and Angular
In the modern web development world, React, Vue, and Angular are the three main pillars for building dynamic and interactive user interfaces. Each of these frameworks and libraries came with different philosophies, but all were designed to solve one fundamental problem: efficient State management in web applications.
Why Are These Three Similar?
At first glance, these three tools may seem completely different, but deep down, they share significant commonalities:
Component-based Architecture: All three use the concept of reusable components. You divide the UI into small, independent pieces, each with its specific responsibility.
Reactive Rendering: They all benefit from a data-driven pattern - when data changes, the UI automatically updates. This is one of their biggest advantages over vanilla JavaScript.
State Management: All three offer built-in or integrated solutions for application state management - from useState in React to reactive data in Vue and Services in Angular.
What Do They Do?
These tools are designed for building Single Page Applications (SPAs) and dynamic user interfaces in the browser. They allow you to:
- Build complex web applications that feel like desktop applications
- Create smooth and fast user experiences without page reloads
- Write maintainable and scalable code
In the first part of this article, we’ll examine the core concepts:
- Component Structure
- Data Interpolation
- State Management
- Event Handling
- Control Flow (Loops & Conditionals)
- Forms and Two-Way Binding
- Lifecycle/Effects
- Styling
1. Component Structure
All three tools use “components”. A component is an independent piece of code (like a button or header) that contains HTML, CSS, and Logic (JavaScript).
- React: Uses JSX (HTML inside JavaScript).
- Vue: Uses Single File Component system (separate
<template>,<script>,<style>sections). - Angular: Uses Class and Decorators and typically keeps HTML and CSS files separate.
Example (A Simple Hello World Component):
React (Function Component):
function App() { // Program logic goes here return ( <div> <h1>Hello World!</h1> </div> );}export default App;Vue (Composition API):
<template> <div> <h1>Hello World!</h1> </div></template>
<script setup> // Program logic goes here</script>Angular (Component Decorator):
import { Component } from '@angular/core';
@Component({ selector: 'app-root', template: `<div><h1>Hello World!</h1></div>`,})export class AppComponent { // Program logic goes here}2. Data Interpolation and Variables
How do we display a JavaScript variable on the page?
- React: Use single curly braces
{ }. - Vue: Use double curly braces
{{ }}(known as Mustache syntax). - Angular: Use double curly braces
{{ }}(like Vue).
Example:
React:
function App() { const name = "Ali"; return <h1>Hello {name}</h1>; // Single brace}Vue:
<script setup> const name = "Ali";</script>
<template> <h1>Hello {{ name }}</h1> <!-- Double braces --></template>Angular:
export class AppComponent { name = "Ali";}// In template: <h1>Hello {{ name }}</h1>3. State Management - Most Important Section
When data changes, the UI must update. This changeable data is called State.
- React: Uses the
useStatehook. You cannot directly change the variable; you must use the “setter” function. - Vue: Uses
ref(in the modern Composition API). You change the variable directly but must access.value. - Angular: Uses Class Properties. Variable changes are automatically tracked by Zone.js (or recently with Signals).
Example (Counter):
React:
import { useState } from 'react';
function Counter() { const [count, setCount] = useState(0); // Define state
const increment = () => setCount(count + 1);
return <button onClick={increment}>Count: {count}</button>;}Vue:
<script setup>import { ref } from 'vue';
const count = ref(0); // Define state
const increment = () => count.value++;</script>
<template> <button @click="increment">Count: {{ count }}</button></template>Angular:
export class CounterComponent { count = 0; // Simple state definition
increment() { this.count++; }}// In HTML:// <button (click)="increment()">Count: {{ count }}</button>Getting Input from Parent (Props / Input)
In component-based architecture, you need to send data from the Parent component to the Child component. This data is called Props (short for Properties).
- React: Props are sent as function arguments to the component.
- Vue: You must specify which props you receive in the child component (
defineProps). - Angular: Uses the
@Input()decorator to specify input variables.
Assumption: A UserCard that receives name.
React (Props)
Child
export function UserCard({ name }) { return <p>User: {name}</p>;}Parent
<UserCard name="Ali" />Vue (Props)
Child
<script setup>defineProps({ name: String })</script>
<template> <p>User: {{ name }}</p></template>Parent
<UserCard name="Ali" />Angular (@Input)
Child
import { Component, Input } from '@angular/core';
@Component({ selector: 'app-user-card', template: `<p>User: {{name}}</p>`})export class UserCardComponent { @Input() name = '';}Parent
<app-user-card [name]="'Ali'"></app-user-card>Outputting to Parent (Event / Emit / Output)
React (callback prop)
Child
export function AddButton({ onAdd }) { return <button onClick={onAdd}>Add</button>;}Parent
<AddButton onAdd={() => setCount(c => c + 1)} />Vue (emit)
Child
<script setup>const emit = defineEmits(['add'])</script>
<template> <button @click="emit('add')">Add</button></template>Parent
<AddButton @add="count++" />Angular (@Output + EventEmitter)
Child
import { Component, EventEmitter, Output } from '@angular/core';
@Component({ selector: 'app-add-button', template: `<button (click)="add.emit()">Add</button>`,})export class AddButtonComponent { @Output() add = new EventEmitter<void>();}Parent
<app-add-button (add)="count = count + 1"></app-add-button>4. Event Handling
How do we manage user clicks or typing?
- React: Uses camelCase words like
onClick,onChange. - Vue: Uses the
@directive (orv-on:). For example,@click. - Angular: Uses parentheses
( ). For example,(click).
Example (Calling a function on click):
React:
<button onClick={handleClick}>Click Me</button>Vue:
<button @click="handleClick">Click Me</button>Angular:
<button (click)="handleClick()">Click Me</button>5. Loops & Conditionals
How do we display lists or hide something?
- React: Everything is pure JavaScript. Use
map()for loops and the ternary operator? :or&&for conditions. - Vue: Uses special HTML directives like
v-forandv-if. - Angular: Uses structural directives like
*ngForand*ngIf(or new syntax@for,@ifin newer versions).
Example (Displaying a list of users):
Assume we have an array called users: ['Ali', 'Reza'].
React (using map):
<ul> {users.map((user, index) => ( <li key={index}>{user}</li> ))}</ul>Vue (using v-for):
<ul> <li v-for="(user, index) in users" :key="index"> {{ user }} </li></ul>*Angular (using ngFor):
<ul> <li *ngFor="let user of users; let i = index"> {{ user }} </li></ul>Example (Conditional rendering - if admin):
React:
{isAdmin ? <p>You are admin</p> : <p>Regular user</p>}Vue:
<p v-if="isAdmin">You are admin</p><p v-else>Regular user</p>Angular:
<p *ngIf="isAdmin; else userBlock">You are admin</p><ng-template #userBlock><p>Regular user</p></ng-template>Note: In Angular 17+ the syntax @if (isAdmin) { ... } was added which is similar to JavaScript.
6. Forms and Two-Way Data Binding
When the user types something in an input, we want our variable to update simultaneously and vice versa.
- React: One-way by default. You must connect the
valueto state and update state inonChange(Controlled Component). - Vue: Has a magical feature called
v-modelthat makes this very simple. - Angular: Has a syntax known as “banana in a box”
[( )]:[(ngModel)].
Example (Typing in input and displaying text simultaneously):
React (manual):
function Form() { const [text, setText] = useState('');
return ( <div> <input value={text} onChange={(e) => setText(e.target.value)} /> <p>You wrote: {text}</p> </div> );}Vue (automatic with v-model):
<script setup> import { ref } from 'vue'; const text = ref('');</script>
<template> <input v-model="text" /> <p>You wrote: {{ text }}</p></template>Angular (automatic with ngModel):
// Requires importing FormsModule in the moduleexport class FormComponent { text = '';}// HTML:// <input [(ngModel)]="text" />// <p>You wrote: {{ text }}</p>7. Lifecycle - For Example Page Load
Sometimes you want to do something when the component is loaded on the page for the first time (for example, fetching data from server/API).
- React: Uses the
useEffecthook with an empty dependency array[]. - Vue: Uses the
onMountedhook. - Angular: Uses the
OnInitinterface and thengOnInitmethod.
Example (Logging a message when component loads):
React:
import { useEffect } from 'react';
function App() { useEffect(() => { console.log("Component loaded!"); // Here we make API requests }, []);
return <div>Content</div>;}Vue:
<script setup>import { onMounted } from 'vue';
onMounted(() => { console.log("Component loaded!");});</script>Angular:
import { Component, OnInit } from '@angular/core';
export class AppComponent implements OnInit { ngOnInit() { console.log("Component loaded!"); }}8. Styling (CSS Styles)
How do we add color and styling to components?
- React: Has many methods. The simplest is
import './App.css'or inline style as a JavaScript object. - Vue: Has a
<style>tag in the same component file. If you add thescopedattribute, styles only apply to that component (very popular). - Angular: In the component file, links a file like
styleUrls: ['./app.component.css']. Angular isolates (scopes) styles by default.
Example (Making text red):
React (Inline Style Object):
// Style in React is an object, not a string// background-color becomes backgroundColor<div style={{ color: 'red', fontSize: '20px' }}> Red text</div>Vue (Scoped CSS):
<template> <div class="my-text">Red text</div></template>
<style scoped>/* This class only works in this file */.my-text { color: red; font-size: 20px;}</style>Angular (External SCSS/CSS):
@Component({ // ... styles: [` .my-text { color: red; font-size: 20px; } `]})Conclusion
As we saw, all three (React / Vue / Angular) are built for creating browser-based applications. The “common idea” is: we break the UI into small components, keep data, change it uniformly with events, and the UI updates with data changes. The main difference is in syntax and default tools.
This concludes the first series of simultaneous comparison articles on react-vue-angular.
If you have any comments or suggestions, I’d be happy if you leave a comment right here, and hope to see you again.
What is your opinion?