Este artículo comienza explicando el Modelo MVVM y luego muestra las Propiedades Directivas y Eventos de los Componentes en VUE lo cual puede ser una guía rápida y muy útil para programar y tener en cuenta las diferentes opciones que el programador del front end tiene.
Si deseas aprender sobre programación en Java sigue este link.
1. Modelo MVVM
El Modelo – Vista – Vista Modelo MVVM de VUE establece diferentes mecanismos de comunicación usando Propiedades Directivas y Eventos entre la lógica y especialmente los datos contenidos en la sección data de la instancia de VUE y los elementos de la vista. De esta forma se tienen 4 posibles mecanismos definidos para comunicarnos entre estos dos elementos (datos y elementos de la página web)
- Una vez: este mecanismo determina que un dato se utiliza en los componentes HTML o DOM de la página web una sola vez, de esta forma si el dato cambia no se vera reflejado en la página web.
- Una dirección: este mecanismo implica que un dato se utiliza en los componentes HTML o DOM de la página web y cada vez que el dato cambie, normalmente por instrucciones en la lógica JS este cambio se vera reflejado o refrescado en la página web.
- Invertido: este mecanismo implica que un dato de la página web puede refrescarse o actualizarse en una variable que se tenga en la sección de JS, un buen ejemplo de esto ocurre en los formularios en los cuales el usuario ingresa información y esta será requerida en la lógica para realizar algún proceso como validaciones o envío al back end para el procesamiento.
- Dos direcciones o bidireccional: los datos en esta modalidad de comunicación serán actualizados en la página web y en el javascript, de tal forma que un cambio se vea reflejado en tanto en la lógica como en el HTML o viceversa.
2. Propiedades Directivas y Eventos de los Componentes en VUE
2.1. Directivas v-once
Esta es una de las Propiedades de los Componentes en VUE de la sección HTML indica a la instancia de VUE que la etiqueta se muestre solo una vez por lo cual es muy útil para depurar. De esta manera, aunque existan actualizaciones de las variables estas no serán tenidas en cuenta y no se actualizará el componente a excepción de la primera vez.
<span v-once>Entrada</span>
2.2. Directivas v-bind
Esta es otra de las Propiedad de de los Componentes en VUE y permite actualizar datos de la vista, recuerde que también se realizó con el render declarativo, pero v-bind permite enlazar data a atributos de HTML.
En la sección HTML del siguiente ejemplo se muestra como vincular en atributo src de una etiqueta img a una variable de forma que el atributo sea dinámico, note que el uso de v-bind es opcional y se puede simplificar significativamente usando solo dos puntos.
Algo muy importante del v-bind es que se puede usar para propiedades como el class que define el estilo CSS aplicado a una etiqueta, esto permite programáticamente cambiar los estilos usando variables que contengan el nombre de la clase CSS que queremos aplicar a la etiqueta.
<!-- #################################################################################### -->
<!-- ###### Sección de HTML ###### -->
<!-- #################################################################################### -->
<template>
<div id="nav" class="principal">
<span v-once>Entrada</span>
<img v-bind:src="imagen"></img>
<img :src="imagen"></img>
</div>
</template>
<!-- #################################################################################### -->
<!-- ###### Sección de Script ###### -->
<!-- #################################################################################### -->
<script>
export default {
name: 'Entrada',
data() {
return {
imagen: 'https://www.ochoscar.com/wp-content/uploads/2022/08/cropped-cropped-logoh-transparente.png'
}
}
}
</script>
2.3. Directivas v-on
La Propiedad maneja Eventos de los Componentes en VUE, v-on nos va a permitir capturar eventos de los elementos HTML y procesarlos a través de métodos de JavaScript. En el siguiente ejemplo se muestra como hacerlo.
Un punto importante y muy usado es que similarmente a como sucedia con v-bind en el caso de v-on se puede abreviar usando @ de esta manera no es necesario escribir v-on: sino que en su lugar simplemente se escribe la @
<!-- #################################################################################### -->
<!-- ###### Sección de HTML ###### -->
<!-- #################################################################################### -->
<template>
<div id="nav" class="principal">
<span v-once>Entrada</span>
<button v-on:click="processClick()">click me</button>
</div>
</template>
<!-- #################################################################################### -->
<!-- ###### Sección de Script ###### -->
<!-- #################################################################################### -->
<script>
export default {
name: 'Entrada',
methods: {
processClick() {
console.log("click en boton")
}
}
}
</script>
Otros eventos que son muy útiles y normalmente utilizados son:
- mousemove: sucede cuando el mouse pasa por encima del componente.
- mousedown: sucede cuando el click principal del mouse se presiona.
- mouseup: sucede cuando el click principal del mouse se suelta.
- keydown: ocurre cuando se presiona una tecla.
- keyup: ocurre cuando se suelta una tecla.
Es importante anotar que todos los métodos que procesan eventos pueden recibir, aunqque no se especifique en la sección HTML, un parámetro denominado event con la información del evento, por ejemplo la posición del mouse o el texto de una caja de texto.
Los modificadores de eventos también nos van a permitir dar un comportamiento más particular, para ello solamente es indicar después del evento el modificador, por ejemplo @keyup.enter solamente se disparará el evento si la tecla es enter, o por ejemplo @mousedown.left para controlar un click derecho, en este último caso será conveniente agregar al componente @contextmenu.prevent para evitar procesar el menú contextual del navegador.
2.4. Directivas ref y refs
Esta directiva nos permite referencia componentes de HTML en la sección de JavaScript a fin de poder modificar alguna de sus propiedades.
Esto se logra dando un valor al atributo ref de los componentes HTML y luego para su uso en JavaScript podemos acceder al conjunto de todas las referencias usnaod this.$refs, como se muestra en el ejemplo siguiente, en el cual tenemos un canvas en el lado de HTML y el mismo lo podemos obtener en el lado JavaScript para realizar alguna acción con el mismo.
<!-- #################################################################################### -->
<!-- ###### Sección de HTML ###### -->
<!-- #################################################################################### -->
<template>
<div id="nav" class="principal">
<span v-once>Entrada</span>
<canvas ref="canvas"></canvas>
</div>
</template>
<!-- #################################################################################### -->
<!-- ###### Sección de Script ###### -->
<!-- #################################################################################### -->
<script>
export default {
name: 'Entrada',
data() {
return {
canvasContext: null
}
},
mounted() {
canvasContext = this.$refs.canvas.getContext('2d');
// set strokeSyle (color) y lineWidth
},
methods: {
processClick() {
console.log("click en boton")
}
}
}
</script>
2.7. Directivas v-model
La directiva v-model permite la comunicación bidireccional que se vio en el Modelo MVVM y establecer Propiedades y Eventos de VUE. En este caso un cambio en HTML se verá reflejado en la data asociada con v-model y viceversa.
En el siguiente ejemplo se muestra una variable de data vinculada con v-model en el HTML.
<!-- #################################################################################### -->
<!-- ###### Sección de HTML ###### -->
<!-- #################################################################################### -->
<template>
<div id="nav" class="principal">
<span >Entrada</span>
<input v-model="email">
</div>
</template>
<!-- #################################################################################### -->
<!-- ###### Sección de Script ###### -->
<!-- #################################################################################### -->
<script>
export default {
name: 'Entrada',
data() {
return {
email
}
}
}
</script>
2.8. Directivas props
Los props es un atributo muy conveniente porque permite que en el momento de agregar un componente hecho por nosotros podamos recibir valores del componente padre donde se está insertando el componente hijo. En el siguiente ejemplo se recibe un valor del email desde un componente padre donde se inserta el componente Entrada.
Algunas cosas importante por observar es que el props es un arreglo con los nombres de las propiedades que serán enviadas, lo segundo es que en el momento de enviar el valor se usa v-bind como se aprendió anteriormente. Observe también que la propiedad se comporta como si fuera una etiqueta más de la etiqueta HTML y que la misma va a funcionar como si fuera una variable que estuviera en data.
<!-- #################################################################################### -->
<!-- ###### Sección de HTML ###### -->
<!-- #################################################################################### -->
<template>
<div id="nav" class="principal">
<span >Entrada</span>
<input v-model="email">
</div>
</template>
<!-- #################################################################################### -->
<!-- ###### Sección de Script ###### -->
<!-- #################################################################################### -->
<script>
export default {
name: 'Entrada',
props: ['attrEmail'],
data() {
return {
email
}
}
}
</script>
<!-- #################################################################################### -->
<!-- ###### Sección de HTML ###### -->
<!-- #################################################################################### -->
<template>
<div id="app">
<entrada :attrEmail="email"></entrada>
</div>
</template>
<!-- #################################################################################### -->
<!-- ###### Sección de Script ###### -->
<!-- #################################################################################### -->
<script>
import Usuario from '@/views/Usuario.vue'
import Entrada from '@/views/Entrada.vue'
export default {
name: 'App',
components: { Usuario, Entrada },
data() {
return {
email: "user@email.com"
}
}
}
</script>
2.9. Directivas $emit
Emit permite realizar la comunicación inversa que realiza prop, es decir de los hijos al padre, en este caso la directiva emit nos permitirá lanzar eventos que serán escuchados por el padre.
El siguiente código muestra un evento capturado en el padre y lanzado desde el hijo. En el momento de disparar el evento llamando a emit este recibe dos parametros, el primero es el nombre del evento y el segundo es el nombre del evento a disparar y el segundo el valor.
<!-- #################################################################################### -->
<!-- ###### Sección de HTML ###### -->
<!-- #################################################################################### -->
<template>
<div id="nav" class="principal">
<span >Entrada</span>
<input v-model="email" @keyup.enter="actualizar" type="text">
</div>
</template>
<!-- #################################################################################### -->
<!-- ###### Sección de Script ###### -->
<!-- #################################################################################### -->
<script>
export default {
name: 'Entrada',
props: ['attrEmail'],
data() {
return {
email
}
},
methods: {
actualizar(event) {
this.$emit("onChange", this.email);
}
}
}
</script>
<!-- #################################################################################### -->
<!-- ###### Sección de HTML ###### -->
<!-- #################################################################################### -->
<template>
<div id="app">
<entrada :attrEmail="email" @onChange="change"></entrada>
</div>
</template>
<!-- #################################################################################### -->
<!-- ###### Sección de Script ###### -->
<!-- #################################################################################### -->
<script>
import Usuario from '@/views/Usuario.vue'
import Entrada from '@/views/Entrada.vue'
export default {
name: 'App',
components: { Usuario, Entrada },
data() {
return {
email: "user@email.com"
}
},
methods: {
change(param) {
console.log("change" + param)
}
}
}
</script>
2.10. Directivas v-watch
Esta directiva nos permitirá observar una variable en particular y ejecutar un código cuando esta cambie. Normalmente se observan variables de data, pero se puede observar cualquiera, ya sea de data, de props o de la instancia VUE.
Para observar una variable, es suficiente con declarar en la sección watch un método con exactamente el mismo nombre de la variable como se muestra en el siguiente ejemplo. En el método que trata el cambio se pueden recibir el newValue y el oldValue para realizar comprobaciones y acciones en el momento del cambio.
<!-- #################################################################################### -->
<!-- ###### Sección de HTML ###### -->
<!-- #################################################################################### -->
<template>
<div id="nav" class="principal">
<span >Entrada</span>
<input v-model="email" @keyup.enter="actualizar" type="text">
</div>
</template>
<!-- #################################################################################### -->
<!-- ###### Sección de Script ###### -->
<!-- #################################################################################### -->
<script>
export default {
name: 'Entrada',
props: ['attrEmail'],
data() {
return {
email
}
},
methods: {
actualizar(event) {
this.$emit("onChange", this.email);
}
},
watch: {
attrEmail(newValue, oldValue) {
console.log(this.attrEmail)
}
}
}
</script>
2.11. Directivas v-if y v-show
Esta directiva nos permite mostrar o ocultar elementos de acuerdo a condiciones. Opcionalmente también existe v-else-if y v-else que permiten armar una secuencia de comprobaciones para facilitar la comprobación. Es importante observar que estas condiciones son siempre booleanas y que se pueden definir en la misma sección del atributo HTML.
La directiva v-show es similar a v-if, la diferencia es que utiliza CSS para ocultar o mostrar los elementos en lugar de crearlos o destruirlos del DOM como si lo hace v-if, en general v-show puede ser mejor en términos de recursos de la máquina, sin embargo se pueden visualizar en el DOM si se inspecciona la página.
<!-- #################################################################################### -->
<!-- ###### Sección de HTML ###### -->
<!-- #################################################################################### -->
<template>
<div id="nav" class="principal">
<span v-if="condicion">Entrada</span>
</div>
</template>
<!-- #################################################################################### -->
<!-- ###### Sección de Script ###### -->
<!-- #################################################################################### -->
<script>
export default {
name: 'Entrada',
data() {
return {
condicion: true
}
}
}
</script>
2.12. Directivas v-for
Esta directiva nos permitirá crear elementos HTML desde una lista que tengamos en la lógica. Aquí hay varias cosas importante que anotar, la primera es que en el for se recorrerá con dos variables, la primera que captura el valor del array y la segunda un índice que servirá como key del botón, este key es indispensable definirlo puesto que tendremos varios botones y es necesario diferenciarlos.
Observe también que habiendo construido los botones con los valores del arreglo y con un índice como clave se pueden enviar a un método que procese los eventos de click enviando el identificador del botón para diferenciarlos en el momento de procesar la lógica.
<!-- #################################################################################### -->
<!-- ###### Sección de HTML ###### -->
<!-- #################################################################################### -->
<template>
<div id="nav" class="principal">
<span>Entrada</span>
<button @click="buttonClick(elemento, i)" v-for="(elemento, i) in elementos" :key="i">{{ elemento }}</button>
</div>
</template>
<!-- #################################################################################### -->
<!-- ###### Sección de Script ###### -->
<!-- #################################################################################### -->
<script>
export default {
name: 'Entrada',
data() {
return {
elementos: ['OBJ1', 'OBJ2', 'OBJ3', 'OBJ4', 'OBJ5']
}
},
methods: {
buttonClick(elemento, i) {
console.log("click en: " + elemento + " " + i)
}
}
}
</script>