Como proyecto final del curso, vamos a desarrollar una aplicación completa en Vue.js. Esta aplicación será una SPA (Single Page Application) que permite a los usuarios gestionar una lista de tareas (To-Do List) con autenticación básica. Utilizaremos Vue Router para la navegación, Vuex para la gestión del estado, y Axios para interactuar con una API.
Autenticación de Usuarios:
Gestión de Tareas:
Navegación entre Vistas:
src/
|-- api/
| |-- api.js
|-- components/
| |-- TaskList.vue
| |-- TaskItem.vue
|-- store/
| |-- index.js
| |-- auth.js
| |-- tasks.js
|-- views/
| |-- Home.vue
| |-- Login.vue
| |-- Register.vue
| |-- Tasks.vue
| |-- Profile.vue
|-- App.vue
|-- main.js
|-- router.js
Primero, necesitamos instalar las siguientes dependencias:
npm install vue-router@next vuex@next axios
// src/api/api.js
import axios from 'axios';
const apiClient = axios.create({
baseURL: 'https://example.com/api',
withCredentials: true,
headers: {
Accept: 'application/json',
'Content-Type': 'application/json'
}
});
export default apiClient;
// src/router.js
import { createRouter, createWebHistory } from 'vue-router';
import Home from './views/Home.vue';
import Login from './views/Login.vue';
import Register from './views/Register.vue';
import Tasks from './views/Tasks.vue';
import Profile from './views/Profile.vue';
const routes = [
{ path: '/', component: Home },
{ path: '/login', component: Login },
{ path: '/register', component: Register },
{ path: '/tasks', component: Tasks, meta: { requiresAuth: true } },
{ path: '/profile', component: Profile, meta: { requiresAuth: true } }
];
const router = createRouter({
history: createWebHistory(),
routes
});
router.beforeEach((to, from, next) => {
const loggedIn = localStorage.getItem('user');
if (to.matched.some(record => record.meta.requiresAuth) && !loggedIn) {
next('/login');
} else {
next();
}
});
export default router;
on',
'Content-Type': 'application/json'
}
});
export default apiClient;
// src/store/index.js
import { createStore } from 'vuex';
import auth from './auth';
import tasks from './tasks';
const store = createStore({
modules: {
auth,
tasks
}
});
export default store;
// src/store/auth.js
import apiClient from '../api/api';
const state = {
user: JSON.parse(localStorage.getItem('user')) || null
};
const mutations = {
setUser(state, user) {
state.user = user;
},
logout(state) {
state.user = null;
}
};
const actions = {
async login({ commit }, credentials) {
const response = await apiClient.post('/login', credentials);
const user = response.data;
localStorage.setItem('user', JSON.stringify(user));
commit('setUser', user);
},
async register({ commit }, userData) {
const response = await apiClient.post('/register', userData);
const user = response.data;
localStorage.setItem('user', JSON.stringify(user));
commit('setUser', user);
},
logout({ commit }) {
localStorage.removeItem('user');
commit('logout');
}
};
const getters = {
isAuthenticated: state => !!state.user
};
export default {
namespaced: true,
state,
mutations,
actions,
getters
};
// src/store/tasks.js
import apiClient from '../api/api';
const state = {
tasks: []
};
const mutations = {
setTasks(state, tasks) {
state.tasks = tasks;
},
addTask(state, task) {
state.tasks.push(task);
},
updateTask(state, updatedTask) {
const index = state.tasks.findIndex(task => task.id === updatedTask.id);
if (index !== -1) {
state.tasks.splice(index, 1, updatedTask);
}
},
deleteTask(state, taskId) {
state.tasks = state.tasks.filter(task => task.id !== taskId);
}
};
const actions = {
async fetchTasks({ commit }) {
const response = await apiClient.get('/tasks');
commit('setTasks', response.data);
},
async addTask({ commit }, task) {
const response = await apiClient.post('/tasks', task);
commit('addTask', response.data);
},
async updateTask({ commit }, task) {
const response = await apiClient.put(`/tasks/${task.id}`, task);
commit('updateTask', response.data);
},
async deleteTask({ commit }, taskId) {
await apiClient.delete(`/tasks/${taskId}`);
commit('deleteTask', taskId);
}
};
const getters = {
allTasks: state => state.tasks,
completedTasks: state => state.tasks.filter(task => task.completed),
incompleteTasks: state => state.tasks.filter(task => !task.completed)
};
export default {
namespaced: true,
state,
mutations,
actions,
getters
};
Lista de Tareas
-
{{ task.title }}
Home.vue
Bienvenido a la Lista de Tareas
Ver Tareas
Login.vue
Iniciar Sesión
{{ error }}
Register.vue
Registrarse
{{ error }}
Tasks.vue
Mis Tareas
Profile.vue
Perfil
Usuario: {{ user.email }}
// src/main.js
import { createApp } from 'vue';
import App from './App.vue';
import router from './router';
import store from './store';
const app = createApp(App);
app.use(router);
app.use(store);
app.mount('#app');
Hemos desarrollado una aplicación completa en Vue.js que incluye: