JavaScript Unlocked: Effortlessly Master React, Vue, and Angular

bilel salem - May 20 - - Dev Community

Introduction

If you've mastered JavaScript, you'll find that learning front-end frameworks like React, Vue, and Angular becomes significantly easier. These frameworks share many underlying principles and patterns, which means that once you become proficient in one, you'll find it much simpler to pick up the others. Understanding JavaScript fundamentals such as state management, component-based architecture, event handling, and two-way data binding will give you a strong foundation to navigate and excel in any of these frameworks.

In this guide, we'll compare React, Vue, and Angular by looking at how they handle common tasks such as state management, component lifecycle, refs, props, two-way data binding, and event emission from child to parent components. By understanding these core concepts in each framework, you'll see just how similar they are and how your JavaScript skills can be seamlessly transferred from one to another.

State Management:

React

In React, state management within a component is handled using hooks such as useState:

import React, { useState } from 'react';

function MyComponent() {
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={() => setCount(count + 1)}>Increment</button>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

Angular

In Angular, state is typically managed using services and BehaviorSubject from RxJS for more complex state management:

// counter.service.ts
import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs';

@Injectable({
  providedIn: 'root',
})
export class CounterService {
  private countSubject = new BehaviorSubject<number>(0);
  count$ = this.countSubject.asObservable();

  increment() {
    this.countSubject.next(this.countSubject.value + 1);
  }
}

// my-component.component.ts
import { Component } from '@angular/core';
import { CounterService } from './counter.service';

@Component({
  selector: 'app-my-component',
  template: `
    <div>
      <p>Count: {{ count | async }}</p>
      <button (click)="increment()">Increment</button>
    </div>
  `,
})
export class MyComponent {
  count = this.counterService.count$;

  constructor(private counterService: CounterService) {}

  increment() {
    this.counterService.increment();
  }
}
Enter fullscreen mode Exit fullscreen mode

Vue

In Vue, state can be managed using the data option for local state and Vuex for more complex state management:

// MyComponent.vue
<template>
  <div>
    <p>Count: {{ count }}</p>
    <button @click="increment">Increment</button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      count: 0,
    };
  },
  methods: {
    increment() {
      this.count += 1;
    },
  },
};
</script>
Enter fullscreen mode Exit fullscreen mode

Component Lifecycle:

React

React uses lifecycle methods like useEffect to handle side effects:

import React, { useEffect } from 'react';

function MyComponent() {
  useEffect(() => {
    console.log('Component mounted');
    return () => {
      console.log('Component unmounted');
    };
  }, []);

  return <div>My Component</div>;
}
Enter fullscreen mode Exit fullscreen mode

Angular

Angular lifecycle hooks are methods like ngOnInit and ngOnDestroy:

import { Component, OnInit, OnDestroy } from '@angular/core';

@Component({
  selector: 'app-my-component',
  template: '<div>My Component</div>',
})
export class MyComponent implements OnInit, OnDestroy {
  ngOnInit() {
    console.log('Component mounted');
  }

  ngOnDestroy() {
    console.log('Component unmounted');
  }
}
Enter fullscreen mode Exit fullscreen mode

Vue

Vue lifecycle hooks include methods like mounted and beforeDestroy:

export default {
  template: '<div>My Component</div>',
  mounted() {
    console.log('Component mounted');
  },
  beforeDestroy() {
    console.log('Component unmounted');
  },
};
Enter fullscreen mode Exit fullscreen mode

Refs:

React

React uses useRef to reference DOM elements:

import React, { useRef } from 'react';

function MyComponent() {
  const inputRef = useRef(null);

  const focusInput = () => {
    inputRef.current.focus();
  };

  return (
    <div>
      <input ref={inputRef} />
      <button onClick={focusInput}>Focus Input</button>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

Angular

In Angular, ViewChild is used to reference DOM elements:

import { Component, ViewChild, ElementRef } from '@angular/core';

@Component({
  selector: 'app-my-component',
  template: `
    <input #inputElement />
    <button (click)="focusInput()">Focus Input</button>
  `,
})
export class MyComponent {
  @ViewChild('inputElement') inputElement: ElementRef;

  focusInput() {
    this.inputElement.nativeElement.focus();
  }
}
Enter fullscreen mode Exit fullscreen mode

Vue

Vue uses the ref attribute to reference DOM elements:

<template>
  <div>
    <input ref="inputElement" />
    <button @click="focusInput">Focus Input</button>
  </div>
</template>

<script>
export default {
  methods: {
    focusInput() {
      this.$refs.inputElement.focus();
    },
  },
};
</script>
Enter fullscreen mode Exit fullscreen mode

Component Props:

React

In React, props are passed to components via attributes:

function MyComponent({ message }) {
  return <div>{message}</div>;
}

// Usage
<MyComponent message="Hello, World!" />
Enter fullscreen mode Exit fullscreen mode

Angular

In Angular, @Input is used to pass data to child components:

import { Component, Input } from '@angular/core';

@Component({
  selector: 'app-my-component',
  template: '<div>{{ message }}</div>',
})
export class MyComponent {
  @Input() message: string;
}

// Usage in a parent component template
<app-my-component [message]="'Hello, World!'"></app-my-component>
Enter fullscreen mode Exit fullscreen mode

Vue

In Vue, props are passed via attributes in the template:

<template>
  <div>{{ message }}</div>
</template>

<script>
export default {
  props: ['message'],
};
</script>

<!-- Usage -->
<MyComponent message="Hello, World!" />
Enter fullscreen mode Exit fullscreen mode

Two-Way Binding:

React

React does not have built-in two-way binding. State is updated via callbacks:

function MyComponent() {
  const [value, setValue] = useState('');

  return (
    <input
      value={value}
      onChange={(e) => setValue(e.target.value)}
    />
  );
}
Enter fullscreen mode Exit fullscreen mode

Angular

Angular provides two-way binding with ngModel:

import { Component } from '@angular/core';

@Component({
  selector: 'app-my-component',
  template: '<input [(ngModel)]="value" />',
})
export class MyComponent {
  value: string = '';
}
Enter fullscreen mode Exit fullscreen mode

Vue

Vue offers two-way binding with the v-model directive:

<template>
  <input v-model="value" />
</template>

<script>
export default {
  data() {
    return {
      value: '',
    };
  },
};
</script>
Enter fullscreen mode Exit fullscreen mode

Child-Parent Communication (Event Emission):

Vue

In Vue, a child component can emit an event, and the parent component can listen for that event and respond accordingly.

Child Component (MyChildComponent.vue):

<template>
  <button @click="notifyParent">Click me</button>
</template>

<script>
export default {
  methods: {
    notifyParent() {
      this.$emit('childClicked', 'Some data from child');
    },
  },
};
</script>
Enter fullscreen mode Exit fullscreen mode

Parent Component (MyParentComponent.vue):

<template>
  <div>
    <MyChildComponent @childClicked="handleChildClick" />
  </div>
</template>

<script>
import MyChildComponent from './MyChildComponent.vue';

export default {
  components: {
    MyChildComponent,
  },
  methods: {
    handleChildClick(data) {
      console.log('Event received from child:', data);
    },
  },
};
</script>
Enter fullscreen mode Exit fullscreen mode

React

In React, this is typically handled by passing a callback function as a prop to the child component. The child component calls this function to notify the parent component.

Child Component (MyChildComponent.js):

function MyChildComponent({ onChildClick }) {
  return (
    <button onClick={() => onChildClick('Some data from child')}>Click me</button>
  );
}

export default MyChildComponent;
Enter fullscreen mode Exit fullscreen mode

Parent Component (MyParentComponent.js):

import React from 'react';
import MyChildComponent from './MyChildComponent';

function MyParentComponent() {
  const handleChildClick = (data) => {
    console.log('Event received from child:', data);
  };

  return (
    <div>
      <MyChildComponent onChildClick={handleChildClick} />
    </div>
  );
}

export default MyParentComponent;
Enter fullscreen mode Exit fullscreen mode

Angular

In Angular, child components emit events using EventEmitter, and the parent component listens for these events.

Child Component (my-child.component.ts):

import { Component, Output, EventEmitter

 } from '@angular/core';

@Component({
  selector: 'app-my-child',
  template: '<button (click)="notifyParent()">Click me</button>',
})
export class MyChildComponent {
  @Output() childClicked = new EventEmitter<string>();

  notifyParent() {
    this.childClicked.emit('Some data from child');
  }
}
Enter fullscreen mode Exit fullscreen mode

Parent Component (my-parent.component.ts):

import { Component } from '@angular/core';

@Component({
  selector: 'app-my-parent',
  template: '<app-my-child (childClicked)="handleChildClick($event)"></app-my-child>',
})
export class MyParentComponent {
  handleChildClick(data: string) {
    console.log('Event received from child:', data);
  }
}
Enter fullscreen mode Exit fullscreen mode

Summary:

  • React: Uses hooks and props to manage state and communication. It's flexible and allows for custom solutions.
  • Vue: Offers a balance of structure and flexibility with built-in directives like v-model and event emission through $emit.
  • Angular: Provides a comprehensive framework with built-in solutions for state management, communication, and two-way binding using services, EventEmitter, and ngModel.

Understanding these core concepts in each framework will allow you to leverage your JavaScript skills and easily transition between React, Vue, and Angular, making you a versatile and effective front-end developer.

. . . . . . . . . . . . . . . . . . . . . . .