Modern web applications can separate concerns by decoupling the UI (HTML, CSS, JS) from the data and business logic managed by Angular, Vue, or React. This architecture enables design-driven development where front-end developers control UI/UX while developers manage the appβs logic via APIs.
- π¨ Design Flexibility: Front-end developers can build UI freely without framework constraints.
- π οΈ Maintainability: UI and business logic can be updated independently.
- β‘ Performance: Eliminates unnecessary re-renders by reducing framework involvement in UI rendering.
- π Scalability: APIs become reusable across different platforms (web, mobile, other frontends).
- π Static HTML templates serve as the view layer.
- π Modern CSS manages styles and responsiveness.
- π JavaScript fetches data via an API and updates the UI dynamically.
- Frameworks are used solely for managing data, business rules, and API interactions.
- The UI is updated dynamically via API calls.
Each example fetches data via an API and injects it into a vanilla HTML file.
Using Angular Services for data handling while keeping UI separate.
<!-- index.html -->
<table id="ipTable">
<thead>
<tr>
<th>IP Address</th>
<th>Status</th>
</tr>
</thead>
<tbody></tbody>
</table>
<script>
fetch('https://67d944ca00348dd3e2aa65f4.mockapi.io/ip-addresses')
.then(response => response.json())
.then(data => {
const tbody = document.querySelector("#ipTable tbody");
tbody.innerHTML = data.map(ip => `<tr><td>${ip.address}</td><td>${ip.status}</td></tr>`).join("");
});
</script>// src/app/services/ip.service.ts
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';
@Injectable({ providedIn: 'root' })
export class IpService {
private apiUrl = 'https://67d944ca00348dd3e2aa65f4.mockapi.io/ip-addresses';
constructor(private http: HttpClient) {}
getIpAddresses(): Observable<any> {
return this.http.get(this.apiUrl);
}
}// src/app/components/ip.component.ts
import { Component, OnInit } from '@angular/core';
import { IpService } from '../services/ip.service';
@Component({
selector: 'app-ip',
template: '',
})
export class IpComponent implements OnInit {
constructor(private ipService: IpService) {}
ngOnInit() {
this.ipService.getIpAddresses().subscribe(data => console.log(data));
}
}π Reference: Angular Services & Dependency Injection
Using Vue Pinia/Vuex for API interactions.
(Same as Angular)
// src/store/ipStore.js
import { defineStore } from 'pinia';
import { ref } from 'vue';
export const useIpStore = defineStore('ipStore', () => {
const ipAddresses = ref([]);
async function fetchIpAddresses() {
const res = await fetch('https://67d944ca00348dd3e2aa65f4.mockapi.io/ip-addresses');
ipAddresses.value = await res.json();
}
return { ipAddresses, fetchIpAddresses };
});// src/components/IpComponent.vue
<script setup>
import { useIpStore } from '../store/ipStore';
const store = useIpStore();
store.fetchIpAddresses();
</script>
<template></template>π Reference: Pinia State Management
Using React Context API for API calls.
(Same as Angular)
// src/context/IpContext.js
import { createContext, useState, useEffect } from 'react';
export const IpContext = createContext();
export function IpProvider({ children }) {
const [ipAddresses, setIpAddresses] = useState([]);
useEffect(() => {
fetch('https://67d944ca00348dd3e2aa65f4.mockapi.io/ip-addresses')
.then(res => res.json())
.then(data => setIpAddresses(data));
}, []);
return <IpContext.Provider value={{ ipAddresses }}>{children}</IpContext.Provider>;
}// src/components/IpComponent.js
import { useContext } from 'react';
import { IpContext } from '../context/IpContext';
export default function IpComponent() {
const { ipAddresses } = useContext(IpContext);
console.log(ipAddresses);
return null;
}π Reference: React Context API
By decoupling the presentation layer from Angular, Vue, and React:
β
Designers and front-end developers can freely work with HTML, CSS, and JavaScript.
β
Business logic remains structured within the chosen framework.
β
API-driven data binding enables seamless updates without UI constraints.
- Angular Services & API Calls: https://angular.io/guide/dependency-injection
- Vue Pinia State Management: https://pinia.vuejs.org/
- React Context API: https://react.dev/reference/react/useContext
This write-up aligns with current best practices for separating concerns in web applications while leveraging APIs. π