Iteración de Colecciones con la Directiva v-for
En el desarrollo frontal con Vue, la directiva v-for es fundamental para renderizar listas basadas en arreglos u objetos. Esta directiva permite generar elementos del DOM dinámicamente según los datos del estado.
Uso Básico en Arrays
Para iterar sobre una lista simple, se utiliza la sintaxis item in lista. Cada elemento se vuelve reactivo dentro del scope del elemento DOM.
<html>
<head>
<meta charset="UTF-8">
<title>Ejemplo v-for</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
</head>
<body>
<div id="contenedor-principal">
<ul>
<li v-for="tecnologia in tecnologias">{{ tecnologia }}</li>
</ul>
<hr>
<div v-for="usuario in usuarios">
<p>Usuario: {{ usuario }}</p>
</div>
</div>
<script>
const app = new Vue({
el: '#contenedor-principal',
data: {
tecnologias: ['JavaScript', 'Python', 'Go', 'Rust'],
usuarios: ['Ana', 'Carlos', 'Lucía']
}
})
</script>
</body>
</html>
Gestión de Carrito de Compras
Un caso de uso común es la visualización de productos. Se puede combinar v-for con directivas condicionales como v-if para manejar estados vacíos.
<div id="app-carrito">
<div class="contenido">
<h2>Resumen de Productos</h2>
<p v-if="productos.length === 0">No hay artículos seleccionados.</p>
<table v-else>
<thead>
<tr>
<th>ID</th>
<th>Producto</th>
<th>Precio</th>
</tr>
</thead>
<tbody>
<tr v-for="articulo in productos">
<td>{{ articulo.id }}</td>
<td>{{ articulo.nombre }}</td>
<td>${{ articulo.valor }}</td>
</tr>
</tbody>
</table>
<button @click="inicializarDatos">Cargar Inventario</button>
</div>
</div>
<script>
const vmCarrito = new Vue({
el: '#app-carrito',
data: {
productos: []
},
methods: {
inicializarDatos() {
this.productos = [
{id: 101, nombre: 'Teclado Mecánico', valor: 120},
{id: 102, nombre: 'Monitor 24"', valor: 200},
{id: 103, nombre: 'Ratón Óptico', valor: 45}
]
}
}
})
</script>
Tipos de Datos Iterables
v-for no se limita a arreglos. También puede recorrer objetos, strings y rangos numéricos. La sintaxis varía ligeramente para acceder a claves y valores.
- Objetos:
v-for="(valor, clave) in objeto" - Números:
v-for="n in 10"(itera desde 1 hasta 10)
<div id="demo-tipos">
<h3>Propiedades de Usuario</h3>
<ul>
<li v-for="(valor, clave) in perfil">{{ clave }}: {{ valor }}</li>
</ul>
</div>
<script>
new Vue({
el: '#demo-tipos',
data: {
perfil: { nombre: 'Dev', nivel: 'Senior', activo: true }
}
})
</script>
Manejo de Eventos en el DOM
Vue facilita la escucha de eventos mediante la directiva v-on, o su atajo @. Esto permite ejecutar métodos cuando ocurren interacciones como clicks, cambios de input, etc.
Eventos Comunes en Formularios
Los inputs disparan diversos eventos según la interacción del usuario.
blur: Cuando el elemento pierde el foco.focus: Cuando el elemento recibe el foco.input: Se dispara en cada pulsación de tecla.change: Al confirmar el cambio (ej. perder el foco tras escribir).
Filtrado de Datos en Tiempo Real
Combinando v-model y eventos, se puede crear un buscador dinámico. Es crucial manejar correctamente el contexto this dentro de los callbacks.
<div id="buscador">
<input type="text" v-model="termino" @input="filtrarLista" placeholder="Buscar...">
<ul>
<li v-for="item in resultados">{{ item }}</li>
</ul>
</div>
<script>
new Vue({
el: '#buscador',
data: {
termino: '',
original: ['apple', 'banana', 'orange', 'grape', 'melon'],
resultados: []
},
created() {
this.resultados = this.original;
},
methods: {
filtrarLista() {
// Uso de arrow function para mantener el contexto de 'this'
this.resultados = this.original.filter(elemento =>
elemento.includes(this.termino)
);
}
}
})
</script>
Modificadores de Eventos
Vue ofrece modificadores para tareas comunes sin escribir código extra en los métodos.
.prevent: Ejecutaevent.preventDefault()(útil en formularios o enlaces)..stop: Ejecutaevent.stopPropagation()(detiene la propagación)..once: El evento se dispara máximo una vez..self: Solo dispara si el evento se originó en el elemento mismo, no en sus hijos.
<div id="modificadores">
<!-- Evita recarga de página -->
<form @submit.prevent="guardar">
<button type="submit">Enviar</button>
</form>
<!-- Solo dispara si se hace click directamente en el div, no en el button -->
<div @click.self="accionPadre">
<button @click="accionHijo">Click aquí</button>
</div>
</div>
Enlace Bidireccional con v-model
La directiva v-model crea un enlace de datos bidireccional en elementos de formularios. El valor del input se sincroniza automáticamente con la propiedad del data.
Controles de Formulario
Diferentes inputs requieren diferentes estructuras de datos para el enlace.
- Text/Password: Se enlazan a strings.
- Checkbox (único): Se enlaza a un booleano.
- Checkbox (múltiple): Se enlaza a un arreglo de valores.
- Radio: Se enlazan a un string común que representa el valor seleccionado.
<div id="formulario">
<label>Usuario: <input type="text" v-model="forma.usuario"></label><br>
<label>
<input type="checkbox" v-model="forma.terminos"> Acepto términos
</label><br>
<p>Intereses:</p>
<label><input type="checkbox" v-model="forma.intereses" value="web"> Web</label>
<label><input type="checkbox" v-model="forma.intereses" value="mobile"> Mobile</label><br>
<p>Género:</p>
<label><input type="radio" v-model="forma.genero" value="M"> Masculino</label>
<label><input type="radio" v-model="forma.genero" value="F"> Femenino</label>
<button @click="enviar">Registrar</button>
</div>
<script>
new Vue({
el: '#formulario',
data: {
forma: {
usuario: '',
terminos: false,
intereses: [],
genero: ''
}
},
methods: {
enviar() {
console.log('Datos listos para envío:', this.forma);
}
}
})
</script>
Modificadores Avanzados de v-model
Para controlar cuándo o cómo se sincroniza el dato, v-model acepta modificadores específicos.
.lazy: Syncs after change events instead of input (útil para performacne en inputs costosos)..number: Convierte automáticamente el valor a número..trim: Elimina espacios en blanco al inicio y al final.
<div id="inputs-avanzados">
<!-- Solo actualiza al perder el foco -->
<input v-model.lazy="mensaje" > {{ mensaje }}<br>
<!-- Convierte a número automáticamente -->
<input type="number" v-model.number="edad" > {{ edad + 1 }}<br>
<!-- Elimina espacios extra -->
<input v-model.trim="usuario" >
</div>
<script>
new Vue({
el: '#inputs-avanzados',
data: {
mensaje: '',
edad: 0,
usuario: ''
}
})
</script>