Reglas de Prioridad A: Esenciales
Nota
Esta Guía de Estilo de Vue.js está desactualizada y necesita ser revisada. Si tienes alguna pregunta o sugerencia, por favor abre una incidencia.
Estas reglas ayudan a prevenir errores, así que apréndelas y cúmplelas a toda costa. Pueden existir excepciones, pero deberían ser muy raras y solo ser hechas por aquellos con conocimientos expertos tanto de JavaScript como de Vue.
Usa nombres de componente de varias palabras
Los nombres de los componentes de usuario siempre deben ser de varias palabras, excepto para los componentes App raíz. Esto previene conflictos con elementos HTML existentes y futuros, ya que todos los elementos HTML son de una sola palabra.
Mal
template
<!-- in pre-compiled templates -->
<Item />
<!-- in in-DOM templates -->
<item></item>Bien
template
<!-- in pre-compiled templates -->
<TodoItem />
<!-- in in-DOM templates -->
<todo-item></todo-item>Usa definiciones de prop detalladas
En el código comprometido, las definiciones de prop siempre deben ser lo más detalladas posible, especificando al menos el tipo (o tipos).
Explicación Detallada
Las definiciones de prop detalladas tienen dos ventajas:
- Documentan la API del componente, de modo que es fácil ver cómo se debe utilizar el componente.
- En desarrollo, Vue te advertirá si a un componente se le proporcionan
propscon formato incorrecto, ayudándote a detectar posibles fuentes de error.
Mal
js
// This is only OK when prototyping
const props = defineProps(['status'])Bien
js
const props = defineProps({
status: String
})js
// Even better!
const props = defineProps({
status: {
type: String,
required: true,
validator: (value) => {
return ['syncing', 'synced', 'version-conflict', 'error'].includes(
value
)
}
}
})Usa v-for con key
La key con v-for es siempre requerida en los componentes, para mantener el estado interno del componente en el subárbol. Sin embargo, incluso para los elementos, es una buena práctica mantener un comportamiento predecible, como la constancia de objetos en las animaciones.
Explicación Detallada
Supongamos que tienes una lista de tareas (todos):
js
const todos = ref([
{
id: 1,
text: 'Learn to use v-for'
},
{
id: 2,
text: 'Learn to use key'
}
])Luego las ordenas alfabéticamente. Al actualizar el DOM, Vue optimizará la renderización para realizar las mutaciones del DOM más económicas posibles. Eso podría significar eliminar el primer elemento de la tarea, y luego agregarlo de nuevo al final de la lista.
El problema es que hay casos en los que es importante no eliminar elementos que permanecerán en el DOM. Por ejemplo, es posible que desees usar <transition-group> para animar la clasificación de la lista, o mantener el foco si el elemento renderizado es un <input>. En estos casos, añadir una key única para cada elemento (por ejemplo, :key="todo.id") le dirá a Vue cómo comportarse de manera más predecible.
Según nuestra experiencia, es mejor siempre añadir una key única, para que tú y tu equipo simplemente nunca tengan que preocuparse por estos casos extremos. Luego, en los escenarios raros y críticos para el rendimiento donde la constancia de objetos no es necesaria, puedes hacer una excepción consciente.
Mal
template
<ul>
<li v-for="todo in todos">
{{ todo.text }}
</li>
</ul>Bien
template
<ul>
<li
v-for="todo in todos"
:key="todo.id"
>
{{ todo.text }}
</li>
</ul>Evita v-if con v-for
Nunca uses v-if en el mismo elemento que v-for.
Hay dos casos comunes en los que esto puede ser tentador:
Para filtrar ítems en una lista (por ejemplo,
v-for="user in users" v-if="user.isActive"). En estos casos, reemplazauserscon una nueva propiedadcomputedque devuelva tu lista filtrada (por ejemplo,activeUsers).Para evitar renderizar una lista si debe estar oculta (por ejemplo,
v-for="user in users" v-if="shouldShowUsers"). En estos casos, mueve elv-ifa un elemento contenedor (por ejemplo,ul,ol).
Explicación Detallada
Cuando Vue procesa las directivas, v-if tiene una prioridad más alta que v-for, de modo que este template:
template
<ul>
<li
v-for="user in users"
v-if="user.isActive"
:key="user.id"
>
{{ user.name }}
</li>
</ul>Lanzará un error, porque la directiva v-if se evaluará primero y la variable de iteración user no existe en este momento.
Esto podría solucionarse iterando sobre una propiedad computed en su lugar, así:
js
const activeUsers = computed(() => {
return users.filter((user) => user.isActive)
})template
<ul>
<li
v-for="user in activeUsers"
:key="user.id"
>
{{ user.name }}
</li>
</ul>Alternativamente, podemos usar una etiqueta <template> con v-for para envolver el elemento <li>:
template
<ul>
<template v-for="user in users" :key="user.id">
<li v-if="user.isActive">
{{ user.name }}
</li>
</template>
</ul>Mal
template
<ul>
<li
v-for="user in users"
v-if="user.isActive"
:key="user.id"
>
{{ user.name }}
</li>
</ul>Bien
template
<ul>
<li
v-for="user in activeUsers"
:key="user.id"
>
{{ user.name }}
</li>
</ul>template
<ul>
<template v-for="user in users" :key="user.id">
<li v-if="user.isActive">
{{ user.name }}
</li>
</template>
</ul>Usa estilos con ámbito de componente
Para las aplicaciones, los estilos en un componente App de nivel superior y en los componentes de diseño pueden ser globales, pero todos los demás componentes siempre deben tener un ámbito.
Esto solo es relevante para los Single-File Components. No requiere que se use el scoped attribute. El ámbito podría ser a través de CSS modules, una estrategia basada en clases como BEM, u otra librería/convención.
Las librerías de componentes, sin embargo, deberían preferir una estrategia basada en clases en lugar de usar el scoped attribute.
Esto facilita la anulación de estilos internos, con nombres de clases legibles por humanos que no tienen una especificidad demasiado alta, pero que aún es muy poco probable que resulten en un conflicto.
Explicación Detallada
Si estás desarrollando un proyecto grande, trabajando con otros desarrolladores, o a veces incluyes HTML/CSS de terceros (por ejemplo, de Auth0), un ámbito consistente asegurará que tus estilos solo se apliquen a los componentes para los que están destinados.
Más allá del scoped attribute, usar nombres de clase únicos puede ayudar a asegurar que el CSS de terceros no se aplique a tu propio HTML. Por ejemplo, muchos proyectos usan los nombres de clase button, btn o icon, por lo que incluso si no se utiliza una estrategia como BEM, añadir un prefijo específico de la aplicación y/o del componente (por ejemplo, ButtonClose-icon) puede proporcionar cierta protección.
Mal
template
<template>
<button class="btn btn-close">×</button>
</template>
<style>
.btn-close {
background-color: red;
}
</style>Bien
template
<template>
<button class="button button-close">×</button>
</template>
<!-- Using the `scoped` attribute -->
<style scoped>
.button {
border: none;
border-radius: 2px;
}
.button-close {
background-color: red;
}
</style>template
<template>
<button :class="[$style.button, $style.buttonClose]">×</button>
</template>
<!-- Using CSS modules -->
<style module>
.button {
border: none;
border-radius: 2px;
}
.buttonClose {
background-color: red;
}
</style>template
<template>
<button class="c-Button c-Button--close">×</button>
</template>
<!-- Using the BEM convention -->
<style>
.c-Button {
border: none;
border-radius: 2px;
}
.c-Button--close {
background-color: red;
}
</style>







