Crear directivas personalizadas en Vue permite ir más allá de lo que ofrece el framework por defecto y mejorar la UX con reglas reutilizables. Aquí se construye paso a paso una directiva global llamada v-blur para identificar y desactivar pistas sin preview URL en Platzi Music, combinando manipulación del DOM, estilos CSS y validaciones lógicas en componentes.
¿Qué es una directiva personalizada y cuándo conviene?
Las directivas son funciones que manipulan el DOM desde atributos en el template. Cuando las directivas nativas quedan cortas, podemos crear directivas personalizadas para extender la funcionalidad. Se instalan de forma global si se usan en muchos componentes, o local si solo viven en uno o dos.
En Vue, una directiva expone hooks como bind (similar a mounted), update (similar a updated), también unbind y componentUpdated. Cada hook recibe hasta cuatro parámetros: el elemento del DOM (el), el objeto de binding con el value, modifiers y args, y referencias al Virtual DOM actual y previo (newNode, oldNode). En muchos casos, basta con usar el elemento y el binding.
Conceptos clave que se aplican aquí:
Uso de valores truthy/falsy para decidir estilos y estados.
Manipulación del DOM con Vanilla JavaScript: style, querySelectorAll, setAttribute, removeAttribute.
UX consistente: filtro CSS con blur y cursor not-allowed para indicar que no es accionable.
¿Cómo se construye la directiva v-blur paso a paso?
La directiva debe desenfocar imágenes o contenedores cuando el valor asociado (previewUrl) sea falsy, y deshabilitar la interacción con sus botones. Se organiza como un objeto con un método install y un hook bind que delega en una función auxiliar.
¿Cómo aplicar blur, cursor y deshabilitar botones?
Se define una función setBlur(el, binding) que:
Aplica el filtro CSS: el.style.filter = 'blur(3px)' si el valor es falsy; caso contrario 'none'.
Cambia el cursor: 'not-allowed' cuando no hay preview; si no, 'inherit'.
Busca botones internos con querySelectorAll('button') y los deshabilita con setAttribute('disabled', true) cuando el valor es falsy; si es truthy, remueve el atributo con removeAttribute('disabled').
Corregir propiedades de estilo: usar correctamente el.style, no variantes mal escritas.
Cambiar etiquetas <a> por <button> para aprovechar el estado nativo disabled del navegador.
Usar una condicional ternaria o un patrón booleano para decidir estilos y atributos.
¿Cómo se instala y se usa en componentes?
Se instala de forma global para que esté disponible en toda la app y luego se aplica en el componente de pista, pasando como valor la propiedad previewUrl.
¿Cómo reforzar la lógica en métodos para evitar selecciones inválidas?
Además de la señal visual, se bloquea la acción en los métodos que seleccionan o navegan a una pista cuando no existe previewUrl. Patrón de “cortar ejecución” con return temprano.
// track.vue (métodos)methods:{selectTrack(track){if(!track.previewUrl)return;// lógica de selección cuando sí hay preview},goToTrack(track){if(!track.previewUrl)return;// navegación válida cuando sí hay preview}}
Mejoras de UI recomendadas según lo visto:
Reemplazar <a> por <button class="button">.
Usar clases como is-primary e is-warning para estados visuales claros.
Ubicar secciones al mismo nivel (por ejemplo, media y card-content) para un mejor layout.
¿Te gustaría comentar otras ideas de directivas útiles o casos donde combinarías estilos y validaciones lógicas para reforzar la experiencia del usuario?
No era necesario agregar el (!this.track.preview_url) en selectTracky en goToTrack, solo bastaba con poner el bind @click en los buttons y no en el span dentro del button y ya con el disabled de la directiva se desactiva los controles de play/navegación, asi:
Gracias por el aporte. La apreciacion que haces sobre la validacion es correcto. Con el simple hecho de agregar el atributo disabed al button alcanza para interrumpir el proceso y evidentemente lo mas correcto seria enlazar el @click al button y no al span. De todos modos agregar la validacion en el lado del codigo, tambien es una buena practica ya que esos metodos pueden ser utilizados en otro tipo de contexto (como metodos internos o en otras partes de HTML). De esta manera garantizas que eso funcione correctamente en todos lados.
Con respecto a la funcion de la directiva, no creo que mejore el rendimiento pero si es mas practico y mas facil de seguir. Lo que yo hice fue crear una funcion generica que tambien pueda ser aplicada en otros contextos o hooks de la directiva como el update y podar lograr una actualizacion en tiempo real en caso que el valor de preview_url se modifique.
Si mejora el rendimiento, reduce el numero de comparaciones en una tercera parte (imagina cien, mil o mas resultados) ademas de que no es necesario poner estilo con js a los elementos que no tienen binding null por que ese estilo ya lo tienen con css y por esto es innecesario el if dentro del forEach.
la directiva :key es muy importante para éstos casos.
Cuando realice una búsqueda después de otra, la segunda recordaba el blur de la primera, la solución fue aplicar :key="t.id" para que Vuejs reconociera correctamente las nuevas pistas. y refrescara la blur directiva.
Interesante, prácticamente las directivas me permiten ejecutar cierto código cuando el componente está cargando
yo pense que era mas conveniente NO mostrar los Track que no tienen valor para escuchar, por lo que agregue en el método search (dentro de la vista search)
Comparto con ustedes la directiva para que pueda imprimir un sección en su proyecto, espero les sea de ayuda y tengan una idea de como hacer uso delas directivas en vue, para usarlo debe pasarle el id de la sección a imprimir. Ej. v-print=" ‘printBorrowCard’ "
Interesante esto de las directivas. cambiar el comportamiento de los elementos dependiendo del valor en la data
si deseara cambiar el style completo de un elemento como podria asignar esta directiva?.
Primero deberias crear tu directiva y sus funcionalidades. Luego la debes importar local o globalmente.
Localmente es importarla directo en tu archivo vue en el objeto
Globalmente es importarla en un Index.js y luego puedes usarla en cualquier parte de tu aplicacion.
Finalmente solo debes usarla dentro de un elemento de HTML segun con el nombre que le hayas dado:
<p v-mi-directiva></p>
si deseara cambiar el atributo class completo de un elemento como podría asignar esta directiva?.
Es mejor usar binding de las directivas HTML
Además del conjunto predeterminado de directivas incluidas en el núcleo (v-model y v-show), Vue también le permite registrar sus propias directivas personalizadas. la forma primaria de reutilización y abstracción del código son los componentes; sin embargo, puede haber casos en los que necesite un acceso al bajo nivel al DOM en elementos simples, y aquí es donde las directivas personalizadas seguirían siendo útiles.
👌
Creo este capitulo va despues de filtros, puesto que aqui los mencionan.
Esto es correcto, ya mismo reporto el error. Gracias por avisar!
Tendras algun ejemplo de uso para los parametros NewNode y oldNode?
En realidad serian node y oldNode. Ambos contienen referencias del virtual DOM al node que contiene la directiva en cuestion. El valor oldNode solo serviria dentro de los hooks de directivas update o componentUpdated. La diferencia esta en que en oldNode podrias acceder al estado del node antes de que se hayan modificado valores o estado.
Te dejo el link a la documentacion.
¿Ya no está disponible el servidor?:
PLatzi-music
error 404(The deployment could not be found)
Al parecer estaba caido, ahora esta funcionando de nuevo. Gracias por avisarnos!
Gracias
No manda el track al reproductor
pero el api si te lo está trayendo? podemos comenzar el troubleshooting desde ahí
El problema era que el evento estaba enlazado al span y no al button, gracias!