Skip to content

Errores comunes en Vue

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

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

Section titled “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 })

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.

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

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

Section titled “5. Olvidar limpiar los event listeners manuales”

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

7. Aplicar destructuring en datos reactivos

Section titled “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>

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>