vue 3

John Cardozo

John Cardozo

vue 3

qué es vue?

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?

componentes & datos

HTML

CSS

JS

State = Datos de la aplicación

Componentes reutilizables

Single

Page

Aplication

jerarquia de componentes

Reutilización

Comunicación

Modularización

Eficiencia

Single

Page

Aplication

herramientas & librerias básicas de vue

State Management

Routing

Pinia

Vuex

Vue-router

Peticiones a backend

Axios

Fetch

Desarrollo

Vue CLI

Vite

nodejs

Instalación

Verificación

node --version

npm --version

Node Package Manager

Node

inicio del proyecto

inicio del proyecto

configuración inicial del proyecto

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

estructura de archivos del proyecto

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

main.js + index.html

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

routing

routing

vue-router: rutas del lado cliente

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

configuración de las rutas

// 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

carga del archivo de las rutas

// 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

componentes

componentes

estructura de un componente

<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

uso de componentes

<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

propiedades del componente

<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

propiedades dinámicas

<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

:

recorrer arreglo en template: v-for

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

propiedades entre componentes

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>

condicional en el template: v-if

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

clase css dinámica

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

eventos

eventos

eventos del componente: v-on

<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>

$event: objeto del evento

<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

modificador de un 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>

escuchar y emitir eventos: padre e hijo

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

ESCUCHAR Y EMITIR EVENTOS

<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

reactividad

reactividad

reactividad: 2 way-binding - formularios

<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>

reactividad: 2 WAY-BINDING - variables

<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>

ciclo de vida de componentes

ciclo de vida de componentes

ciclo de vida de un componente

beforeCreate

created

beforeMount

mounted

mounted

beforeUpdate

updated

beforeUnmount

unmounted

activated

deactivated

$el disponible

setup

funciones del ciclo de vida

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");
});

peticiones remotas

peticiones remotas

axios: peticiones a servicios remot0s

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

async/await: instrucciones asíncronas

// 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

axios: obtener los datos - GET

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

axios: agregar un dato - POST

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

producción

producción

generar versión para producción

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

john cardozo

johncardozo@gmail.com

Vue 3

By John Cardozo

Vue 3

Vue 3

  • 202