John Cardozo
John Cardozo
Framework para frontend
Soporta Javascript y Typescript
Sitios web & Interfaces de usuario
Creación dinámica de interfaces
Curva fácil de aprendizaje
Rápido y liviano
Virtual DOM
Buena documentación y comunidad
Single Page Applications
Por qué Vue?
HTML
CSS
JS
State = Datos de la aplicación
Componentes reutilizables
Single
Page
Aplication
Reutilización
Comunicación
Modularización
Eficiencia
Single
Page
Aplication
State Management
Routing
Pinia
Vuex
Vue-router
Peticiones a backend
Axios
Fetch
Desarrollo
Vue CLI
Vite
Instalación
Verificación
node --version
npm --version
Node Package Manager
Node
Creación del proyecto usando Vite
npm init vite@latest nombre-proyecto -- --template vue
Instalación de dependencias
cd nombre-proyecto
npm install
Ejecución del proyecto
npm run dev
node_modules
folder de dependencias
public
archivos públicos
src
código fuente
assets
Archivos estáticos internos
components
Componentes de la app
App.vue
Componente principal de la App
main.js
Archivo de ejecución de la App
style.css
Hoja de estilos global
index.html
Única página de la aplicación
package.json
Configuración de la app Nodejs
import { createApp } from 'vue'
import './style.css'
import App from './App.vue'
createApp(App).mount('#app')
<body>
<div id="app"></div>
<script type="module" src="/src/main.js"></script>
</body>
index.html
main.js
punto inicial de la aplicación
Instalación
npm install vue-router@4
<h1>Administrador de Tareas</h1>
<p>
<router-link to="/">Home</router-link>
<router-link to="/about">About</router-link>
</p>
<!-- El componente que haga match se muestra aquí -->
<router-view></router-view>
App.vue
<h1>About</h1>
<p>
App hecha por mi
</p>
About.vue
views
Opcional
<h1>Home</h1>
<p>
Inicio de la app
</p>
Home.vue
// Importa los objetos de routing
import { createRouter, createWebHistory } from "vue-router";
// Importa las páginas
import Home from "../views/Home.vue";
import About from "../views/About.vue";
// Define las rutas
const routes = [
{ path: "/", component: Home },
{ path: "/about", component: About },
];
// Crea el router
const router = createRouter({
history: createWebHistory(),
routes,
});
export default router;
routes/index.js
// Importar el router
import router from "./router";
// Uso del router en la aplicación
createApp(App)
.use(router)
.mount("#app");
main.js
Pasos para agregar un nuevo view
Crear el view
Registrar la ruta del view
Utilizar router-link para llegar al view
1
2
3
Uso del router en la aplicación
<script setup>
// Javascript
</script>
<template>
<!-- HTML -->
</template>
<style scoped>
/* CSS */
</style>
Componente.vue
<template>
<style>
Lógica del componente: Javascript
<script>
Representación visual del componente: HTML
Hoja de estilos del componente: CSS
SFC: Single File Component
Archivo con extensión .vue
<script setup>
import Header from "./components/Header.vue";
</script>
<template>
<div class="container">
<Header />
</div>
</template>
App.vue
components/Header.vue
<script setup></script>
<template>
<header>
<h1>Administrador de Tareas</h1>
</header>
</template>
Importar el componente
Uso del componente
El nombre del componente es el nombre del archivo sin la extensión
<Header title="Administrador de Tareas" />
App.vue
components/Header.vue
<script setup>
const props = defineProps({
title: String,
});
</script>
<template>
<header>
<h1>{{ title }}</h1>
</header>
</template>
defineProps
Define las propiedades del componente
{ { variable } }
Muestra el valor de una variable en el template
const props = defineProps({
title: {
type: String,
default: "Titulo",
required: true,
},
});
Propiedades con validaciones
Tipos de propiedades
Number,String, Object, Array
<script setup>
import Tareas from "./components/Tareas.vue";
const listaTareas =
[
{ id: 1, title: "running", completed: false },
{ id: 2, title: "reading", completed: true },
{ id: 3, title: "studying", completed: false },
];
</script>
<template>
<Tareas :tareas="listaTareas" />
</template>
App.vue
components/Tareas.vue
<script setup>
const props = defineProps({
tareas: Array,
});
console.log(props.tareas);
</script>
<template>
<div>{{ tareas.length }}</div>
</template>
Se agrega el carácter : antes de la propiedad cuando el valor es dinámico
:
components/Tareas.vue
<script setup>
const tareas = [
{ id: 1, title: "running", completed: false },
{ id: 2, title: "reading", completed: true },
{ id: 3, title: "studying", completed: false },
];
</script>
<template>
<ul>
<li v-for="tarea in tareas" :key="tarea.id">
{{ tarea.title }}
</li>
</ul>
</template>
:key = Indentificador del objeto
Obligatorio
components/Tareas.vue
<script setup>
import Tarea from "./Tarea.vue";
const tareas = [
{ id: 1, title: "running", completed: false },
{ id: 2, title: "reading", completed: true },
{ id: 3, title: "studying", completed: false },
];
</script>
<template>
<h1>Lista de tareas</h1>
<Tarea v-for="tarea in tareas" :key="tarea.id" :tarea="tarea" />
</template>
components/Tarea.vue
<script setup>
const props = defineProps({
tarea: Object,
});
</script>
<template>
<div>
<h2>{{ tarea.title }}</h2>
<p>{{ tarea.completed }}</p>
</div>
</template>
v-if
<p v-if="tarea.length == 0">No hay tareas</p>
v-if / v-else
<p v-if="tarea.completed">Terminada</p>
<p v-else>No terminada</p>
v-if
Evalúa la condición para mostrar el elemento
v-else: opcional
template
<template>
<p :class="tarea.completed ? 'terminada' : 'no-terminada'">
{{ tarea.completed }}
</p>
</template>
Evalua la expresión ternaria y asigna la clase CSS
<style scoped>
.terminada {
color: green;
}
.no-terminada {
color: red;
}
</style>
style
:class
Establece la clase dinámica
<button v-on:click="funcion">boton</button>
<button @click="funcion">boton</button>
<template>
v-on
escucha un evento
@
shortcut
<script setup>
const funcion = () => {
console.log("click");
};
</script>
<script>
<button @:click="funcion($event)">boton</button>
$event: envía el evento a la función
<script setup>
const funcion = (event) => {
console.log(event);
};
</script>
<script>
El argumento recibido en la función tiene todos los datos del evento
<form @submit.prevent="funcion">
<button>boton</button>
</form>
@evento.modificador
Ejemplos de modificadores
@submit.prevent es igual a e.preventDefault()
<!-- El evento 'submit' no recarga la página -->
<form @submit.prevent="onSubmit"></form>
<!-- La función solo se llamar cuando se oprime 'Enter' -->
<input @keyup.enter="funcion" />
<!-- Alt + Enter -->
<input @keyup.alt.enter="clear" />
<!-- Click con el botón derecho -->
<div @click.right="agregarTarea">RIGHT</div>
Padre
Hijo
@
Escucha un evento emitido por el hijo
<Tarea @borrar="funcion" />
emit
Emite un evento al padre
emit("borrar", dato);
Función que se ejecuta en el padre al escuchar el evento
Dato enviado al padre
<script setup>
import Tarea from "./Tarea.vue";
const props = defineProps({
tareas: Array,
});
const borrarTarea = (tarea) => {
console.log(`Borrando en ${tarea.id}...`);
};
</script>
<template>
<h1>Lista de tareas</h1>
<Tarea
v-for="tarea in tareas"
:key="tarea.id"
:tarea="tarea"
@borrar="borrarTarea"
/>
</template>
Tareas.vue
<script setup>
const props = defineProps({
tarea: Object,
});
// Define los eventos a emitir
const emit = defineEmits(["borrar"]);
const borrarHandler = () => {
// Emite un evento al padre
emit("borrar", { id: props.tarea.id });
};
</script>
<template>
<div>
<h2>{{ tarea.title }}</h2>
<p>{{ tarea.completed }}</p>
<span @click="borrarHandler">
Eliminar
</span>
</div>
</template>
Tarea.vue
<script setup>
import { ref } from "vue";
// Declaración de variable reactiva
const titulo = ref();
const agregarTarea = () => {
// Uso de value para obtener el valor de
// la variable reactiva
console.log(`El titulo es ${titulo.value}`)
};
</script>
<template>
<form @submit.prevent="agregarTarea">
<input type="text" v-model="titulo" />
</form>
</template>
directiva v-model
Reactividad para formularios
atributo value
Acceso al valor en <script>
<script setup>
import { ref } from "vue";
let listaTareas = ref([
{ id: 1, title: "running", completed: false },
{ id: 2, title: "reading", completed: true },
{ id: 3, title: "studying", completed: false },
]);
const borrarTarea = (tarea) => {
listaTareas.value = listaTareas.value.filter((t) => {
return t.id != tarea.id;
});
};
</script>
función ref
Reactividad en 2 sentidos
Cuando cambia un valor en <script> se refleja en el template y visceversa
atributo value
Acceso al valor en <script>
beforeCreate
created
beforeMount
mounted
mounted
beforeUpdate
updated
beforeUnmount
unmounted
activated
deactivated
$el disponible
setup
import {
onBeforeMount, onMounted, onBeforeUpdate,
onUpdated, onBeforeUnmount, onUnmounted,
} from "vue";
onBeforeMount(() => {
console.log("onBeforeMount");
});
onMounted(() => {
console.log("onMounted");
});
onBeforeUpdate(() => {
console.log("onBeforeUpdate");
});
onUpdated(() => {
console.log("onUpdated");
});
onBeforeUnmount(() => {
console.log("onBeforeUnmount");
});
onUnmounted(() => {
console.log("onUnmounted");
});
Instalación
npm install axios
[{id:1, title:"correr"}, {id:2, title:"leer"}]
Crear una tarea
Obtener todas las tareas
Modificar una tarea
Eliminar una tarea
POST /tareas
GET /tareas
PATCH /tareas/1
DELETE /tareas/1
{id:1, title:"correr"}
Obtener una tarea
GET /tareas/1
{title: "correr"}
{id:1, title:"correr"}
+
{title: "leer"}
+
{id:1, title:"leer"}
{id:1, title:"leer"}
get
get
post
patch
delete
// Hace la petición al Rest API
let respuesta = axios.get("http://localhost:3000/tareas");
// No muestra la respuesta del servidor
console.log(respuesta);
- Hace la petición al servidor
- Javascript no espera a que se obtenga respuesta
- Ejecuta la siguiente instrucción
Muestra null porque se ejecuta antes de que se obtenga la información del servidor
uso de async/await
async obtenerDatos = () => {
// Hace la petición al Rest API
let respuesta = await axios.get("http://localhost:3000/tareas");
// Muestra la respuesta obtenida del servidor
console.log(respuesta);
}
Para usar await, la instrucción debe estar en un bloque async
import { onMounted } from "vue";
// Lista reactiva
let listaTareas = ref([]);
// Ejecución al montar el componente
onMounted(async () => {
// Llamado de servicio remoto
listaTareas.value = await obtenerTareas();
});
Obtener datos: tareas.js
import axios from "axios";
const obtenerTareas = async () => {
// Uso de axios
let tareas = await axios.get("https://jsonplaceholder.typicode.com/todos");
// Retorna la propiedad Data de axios
return tareas.data;
};
export { obtenerTareas };
Uso en el componente
import { onMounted } from "vue";
// Lista reactiva
let listaTareas = ref([]);
const agregarTareaHandler = async (tarea) => {
// Petición remota
let nuevaTarea = await agregarTarea(tarea);
// Modificación de la información local
listaTareas.value.unshift(nuevaTarea);
};
Agregar un dato: tareas.js
import axios from "axios";
const agregarTarea = async (tarea) => {
let respuesta = await axios.post(
"https://jsonplaceholder.typicode.com/todos",
tarea
);
return respuesta.data;
};
export { agregarTarea };
Uso en el componente
npm run build
scripts de package.json
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview"
},
Comando de generación
Archivos generados
Versión mínima de HTML, CSS y JS
johncardozo@gmail.com