Skip to content

Errores comunes en Vue

1. Omitir index en los v-for

<script setup lang="ts">
import { suffle } from "lodash";
import { ref } from "vue";
const items = ref([
{ id: 1, label: "first name" },
{ id: 2, label: "last name" },
{ id: 3, label: "email" },
{ id: 4, label: "website" },
]);
function suffleItems() {
items.value = suffle(items.value);
}
</script>
<template>
<ul>
<li v-for="item in items">
{{ item.label }}
<input type="text" />
</li>
</ul>
<button @click="suffleItems">Shuffle</button>
</template>

En este caso, se debe agregar el id en el v-for para que Vue pueda identificar cada item de la lista.

<li v-for="{ id, name } in items" :key="id">
{{ name }}
</li>
<li v-for="({ id, name }, index) in items" :key="index">
{{ name }}
</li>

2. Prop drilling

El Prop drilling es un anti-patrón en el que el desarrollador pasa hacia abajo un prop a través de múltiples niveles de componentes simplemente para acceder a datos definidos más arriba en el árbol en un nivel profundamente anidado.

Codificar de esta manera puede llevar a un código difícil de mantener. Para evitar la perforación de props con provide/inject o mediante una solución de gestión de estado global.

3. Ver (watch) Arrays de la forma incorrecta

En el siguiente ejemplo, tenemos un watcher que se encarga de mostrar los cambios en un array.

<script setup lang="ts">
import { ref, watch } from 'vue'
const numbers = ref<number[]>([])
watch(numbers, () => console.log('New number added'))
const addNumber = () => numbers.value.push(Math.random())
</script>
<template>
<button @click="addNumber">Add number</button>
</template>

Pero si miramos en la consola, no aparece nada. El problema es que no estamos mirando el watch en profundidad usando el deep flag.

watch(numbers, () => console.log('New number added'), { deep: true })

¿Por qué es necesario esto?

Si estuvieramos remplazando el array en su totalidad no habría problema. Sin embargo, si estamos mutando el array, o un elemento del array, tenemos que usar el deep flag para que Vue pueda detectar los cambios.

4. ¿Ref o Reactive?

En el video se explica todo este tema con un ejemplo, pero para resumir, usar siempre ref

5. No mutar props

Evitar siempre mutar props, ya que puede llevar a errores inesperados. Para ello, usar siempre un duplicado del prop.

5. Olvidar limpiar los event listeners manuales

Siempre limpiar los event listeners manuales para evitar memory leaks. Ejemplo en el video

6. No usar TypeScript

7. Aplicar destructuring en datos reactivos

En el siguiente ejemplo, estamos aplicando destructuring en un objeto reactivo. El problema es que estamos destruyendo la reactividad del objeto.

<script setup lang="ts">
import { reactive, toRefs } from "vue";
const animal = reactive({
name: "Lion",
diet: "Carnivore",
lifespan: "8-12 years",
});
const { name, diet, lifespan } = animal;
</script>
<template>
<ul>
<li>Name: {{ name }}</li>
<li>Diet: {{ diet }}</li>
<li>Lifespan: {{ lifespan }}</li>
</ul>
</template>

Para solucionar este problema, usamos toRefs. toRefs convierte un objeto reactivo en un objeto de referencias reactivas.

<script setup lang="ts">
import { reactive, toRefs } from "vue";
const animal = reactive({
name: "Lion",
diet: "Carnivore",
lifespan: "8-12 years",
});
const { name, diet, lifespan } = toRefs(animal);
</script>
<template>
<ul>
<li>Name: {{ name }}</li>
<li>Diet: {{ diet }}</li>
<li>Lifespan: {{ lifespan }}</li>
</ul>
</template>

Veamos un ejemplo usando un composable.

import { reactive, toRefs } from "vue";
export const useLion = () => {
const animal = reactive({
name: "Lion",
diet: "Carnivore",
lifespan: "8-12 years",
});
return toRefs(animal);
};

Como podemos ver, es tan sencillo como usar el toRefs en el return del objeto. De esta forma, podemos usar destructuring en el componente sin perder la reactividad.

<script setup>
import { reactive, toRefs } from "vue";
import { useLion } from "@/composables/useLion";
const { diet, lifespan, name } = useLion();
</script>
<template>
<ul>
<li>Name: {{ name }}</li>
<li>Diet: {{ diet }}</li>
<li>Lifespan: {{ lifespan }}</li>
</ul>
</template>

8. Inyectar html en la directiva v-html

La directiva v-html es una directiva de Vue que permite inyectar html en un elemento. Sin embargo, es importante tener en cuenta que esta directiva no es segura y puede llevar a ataques XSS.

Para evitar esto, es importante usar la directiva v-html con precaución y nunca inyectar html de usuarios no confiables. Otro paso a seguir para añadir seguridad, es utilizar la libreria DOMPurify que nos ayudará a limpiar el html inyectado.

Ejemplo de uso de DOMPurify

<p v-html="DOMPurify.sanitize(myCodeHTML)"></p>