Let’s recreate this CRUD project in Vue 3 using the Composition API and <script setup>
. We’ll also use Axios for API requests and JSON Server for the mock backend, similar to the React version.
Step 1: Set up the Vue 3 Project
Create a new Vue 3 project using Vite: Open your terminal and run the following command to create a new Vue 3 project:
npm create vite@latest crud-app-vue --template vue
cd crud-app-vue
Install Axios: Axios will be used for making API requests:
npm install axios
Install JSON Server (if you haven’t already): JSON Server will act as our mock API backend:
npm install json-server
Create a db.json
file: In the root of your project, create a db.json
file to simulate the backend data:
{
"items": [
{ "id": 1, "name": "Item 1", "description": "This is item 1" },
{ "id": 2, "name": "Item 2", "description": "This is item 2" },
{ "id": 3, "name": "Item 3", "description": "This is item 3" }
]
}
Start the JSON Server: Run the following command to start the JSON Server on port 5000:
npx json-server --watch db.json --port 5000
Sure! Let’s recreate this CRUD project in Vue 3 using the Composition API and <script setup>
. We’ll also use Axios for API requests and JSON Server for the mock backend, similar to the React version.
Step 1: Set up the Vue 3 Project
Create a new Vue 3 project using Vite: Open your terminal and run the following command to create a new Vue 3 project:
bashnpm create vite@latest crud-app-vue --template vue cd crud-app-vue
Install Axios: Axios will be used for making API requests:
bashnpm install axios
Install JSON Server (if you haven’t already): JSON Server will act as our mock API backend:
bashnpm install json-server
Create a
db.json
file: In the root of your project, create adb.json
file to simulate the backend data:json{ "items": [ { "id": 1, "name": "Item 1", "description": "This is item 1" }, { "id": 2, "name": "Item 2", "description": "This is item 2" }, { "id": 3, "name": "Item 3", "description": "This is item 3" } ] }
Start the JSON Server: Run the following command to start the JSON Server on port 5000:
bashnpx json-server --watch db.json --port 5000
Step 2: Set up Vue Components
We will use the Composition API with <script setup>
to define our component logic.
Edit
src/App.vue
: Replace the content ofsrc/App.vue
with the following:
<template>
<!-- Main container for the application -->
<div>
<h1>CRUD Application with Vue 3</h1>
<!-- Display the list of items -->
<h2>Items</h2>
<ul>
<!-- Loop through the 'items' array using v-for -->
<li v-for="item in items" :key="item.id">
<!-- If we are editing this item, show the edit form -->
<div v-if="editItem && editItem.id === item.id">
<!-- Input fields for editing the name and description of the item -->
<input
v-model="editItem.name"
placeholder="Edit Name"
/>
<input
v-model="editItem.description"
placeholder="Edit Description"
/>
<!-- Button to save changes to the item -->
<button @click="saveEdit">Save</button>
<!-- Button to cancel the edit -->
<button @click="cancelEdit">Cancel</button>
</div>
<!-- If we are not editing this item, display its details -->
<div v-else>
<!-- Show the item's name and description -->
{{ item.name }} - {{ item.description }}
<!-- Button to initiate editing for this item -->
<button @click="startEdit(item)">Edit</button>
<!-- Button to delete the item -->
<button @click="deleteItem(item.id)">Delete</button>
</div>
</li>
</ul>
<!-- Form to add a new item -->
<h2>Add New Item</h2>
<!-- Input field for the new item's name -->
<input v-model="newItem.name" placeholder="Item Name" />
<!-- Input field for the new item's description -->
<input v-model="newItem.description" placeholder="Item Description" />
<!-- Button to add the new item -->
<button @click="addItem">Add Item</button>
</div>
</template>
<script setup>
import { ref, onMounted } from 'vue'; // Import ref for reactivity and onMounted for lifecycle hook
import axios from 'axios'; // Import axios for making HTTP requests
// Define the structure of an Item with TypeScript's interface (optional if using JS)
interface Item {
id: number; // The unique identifier for each item
name: string; // The name of the item
description: string; // The description of the item
}
// Create a reactive array to hold the list of items
const items = ref<Item[]>([]); // 'items' holds the data fetched from the backend
// Create a reactive object to manage new item input
// Omit 'id' because the server generates it when we add a new item
const newItem = ref<Omit<Item, 'id'>>({ name: '', description: '' });
// Create a reactive object to manage the item being edited, or null if no item is being edited
const editItem = ref<Item | null>(null);
// Function to fetch all items from the server when the component is mounted
const fetchItems = async () => {
try {
// Send a GET request to fetch the list of items
const response = await axios.get<Item[]>('http://localhost:5000/items');
// Update the 'items' array with the data received from the server
items.value = response.data;
} catch (error) {
// Log any error that occurs during the API request
console.error('Error fetching items:', error);
}
};
// Use the onMounted lifecycle hook to fetch items when the component is loaded
onMounted(fetchItems);
// Function to add a new item to the list
const addItem = async () => {
try {
// Send a POST request to add the new item to the server
const response = await axios.post<Item>('http://localhost:5000/items', newItem.value);
// Add the newly created item to the 'items' array
items.value.push(response.data);
// Reset the 'newItem' input fields after successfully adding the item
newItem.value = { name: '', description: '' };
} catch (error) {
// Log any error that occurs during the API request
console.error('Error adding item:', error);
}
};
// Function to start editing an item
const startEdit = (item: Item) => {
// Set 'editItem' to the selected item (creates a copy of the item)
editItem.value = { ...item };
};
// Function to save the edited item
const saveEdit = async () => {
// If no item is being edited, return early
if (!editItem.value) return;
try {
// Send a PUT request to update the item on the server
const response = await axios.put<Item>(`http://localhost:5000/items/${editItem.value.id}`, editItem.value);
// Find the index of the item that was edited in the 'items' array
const index = items.value.findIndex((i) => i.id === editItem.value!.id);
// Replace the old item with the updated item in the 'items' array
items.value[index] = response.data;
// Clear the 'editItem' to exit edit mode
editItem.value = null;
} catch (error) {
// Log any error that occurs during the API request
console.error('Error updating item:', error);
}
};
// Function to cancel the editing process
const cancelEdit = () => {
// Clear the 'editItem' state to cancel editing
editItem.value = null;
};
// Function to delete an item
const deleteItem = async (id: number) => {
try {
// Send a DELETE request to remove the item from the server
await axios.delete(`http://localhost:5000/items/${id}`);
// Update the 'items' array by removing the deleted item
items.value = items.value.filter((item) => item.id !== id);
} catch (error) {
// Log any error that occurs during the API request
console.error('Error deleting item:', error);
}
};
</script>
<style scoped>
/* Scoped CSS to style the component */
ul {
list-style-type: none;
padding: 0;
}
li {
margin-bottom: 10px;
}
button {
margin-left: 10px;
}
</style>
Step 3: Detailed Explanation
Template (
<template>
):- The template contains two main sections:
- A list of items, where each item has options to edit or delete.
- A form to add a new item to the list.
- We use Vue’s
v-for
directive to iterate over theitems
and display each item. - Conditional rendering (
v-if
andv-else
) is used to show the edit form when an item is being edited.
- The template contains two main sections:
Script (
<script setup>
):Reactive Variables:
items
: A reactive array to hold the list of items.newItem
: A reactive object to track the new item’s name and description.editItem
: A reactive object that stores the item being edited (ornull
if no item is being edited).
Lifecycle Hook:
onMounted(fetchItems)
: Fetches the list of items when the component is mounted. This is similar touseEffect
in React.
CRUD Operations:
- Fetch Items (
fetchItems
): Fetches the list of items from the server using a GET request. - Add Item (
addItem
): Adds a new item to the server with a POST request and updates theitems
array. - Start Edit (
startEdit
): Initializes theeditItem
with the selected item. - Save Edit (
saveEdit
): Sends a PUT request to update the item on the server and updates the list of items. - Cancel Edit (
cancelEdit
): Resets theeditItem
state to cancel the edit. - Delete Item (
deleteItem
): Sends a DELETE request to remove the item and updates theitems
array to exclude the deleted item.
- Fetch Items (
Styles (
<style scoped>
):- Some basic CSS styles are provided to make the list and buttons look a bit better.
Step 4: Running the Vue 3 Application
Start JSON Server: Make sure your JSON server is running:
npx json-server --watch db.json --port 5000
Start the Vue Development Server: In a new terminal, start the Vue app:
npm run dev
Open the App: Visit http://localhost:3000
in your browser to see the app in action. You should be able to add, edit, and delete items just like in the React app.
Welcome to DevTechTutor.com, your ultimate resource for mastering web development and technology! Whether you're a beginner eager to dive into coding or an experienced developer looking to sharpen your skills, DevTechTutor.com is here to guide you every step of the way. Our mission is to make learning web development accessible, engaging, and effective.