Vuejs para programadores jQuery. Tabuladores VII

Vuejs para programadores jQuery.


Tabuladores VII


En este post trataremos algo sencillo: Tabulación.



JQUERY


Es tan sencillo que hemos evitado usar el sistema de tabulación de Bootstrap porque lo hace todo automáticamente y no nos valía eso para lo que estamos desarrollando. Perdón por la estética.

Se ha agregado un archivo css local. Si hay dudas de como funciona la clase active se puede revisar el código (para los amantes de sass, como yo, el archivo original es un scss que también está en esa carpeta)


Enlaces:


HTML:


<div class="container top20">

<div class="row">

<div class="tabulacion">

<ul class="tab" id="tab">

<li class="nav-option active" title="home">Home</li>

<li class="nav-option" title="informacion">Información</li>

<li class="nav-option" title="servicios">Servicios</li>

<li class="nav-option" title="contacto">Contacto</li>

</ul>

<div class="content" id="contenidos">

<div class="nav-content active" id="home">

Este es el contenido de home

</div>

<div class="nav-content" id="informacion">

Esta es la información

</div>

<div class="nav-content" id="servicios">

Estos son los servicios

</div>

<div class="nav-content" id="contacto">

Datos de contacto

</div>

</div>

</div>

</div>

</div>


Las opciones son los li del ul con id tab y los contenidos están en dentro del div con id contenidos y cada opción en un div propio con un id igual al title del li correspondiente. Se renderizara diferente la opción que tenga la clase active. Se mostrará el contenido que tenga la clase active.


Veamos como lo resolvemos en jQuery:


const elementos = jQuery('#tab li')

const contenidos = jQuery('#contenidos div')

Este proceso se nos está volviendo rutinario. La constante elementos apunta a todos los elementos li (o sea las opciones de tabulación) y la constante contenidos apunta a todos los div con contenidos.


elementos.on('click', actualiza)


Aquí asociamos todos los eventos click de los li con la función actualiza:


function actualiza(evt) {

contenidos.removeClass('active')

elementos.removeClass('active')

jQuery(evt.target).addClass('active')

jQuery('#' + jQuery(evt.target).attr('title')).addClass('active')

}


Aquí estamos usando un parámetro de la función que no enviamos cuando asociamos la función al evento. Esto es porque los eventos de JS envían un parámetro por defecto. Y también es la razón por la que no usamos los parámetros en la asociación del evento.


Si lo hiciéramos así:


elementos.on('click', actualiza())


Le estaríamos diciendo al evento que no envíe ningún parámetro y por lo tanto el código anterior no funcionaria.


He llamado al evento evt, pero es por costumbrismo. Se le puede llamar como quede más claro.

Una vez dentro de la función eliminamos la clase active de todos los contenidos (recordemos que se mostrara el contenido que tenga esa clase asociada)

Volvemos a eliminar la clase active también de los elementos li.

El evento (evt) es un objeto con varios elementos. Uno de ellos es target que es el objeto sobre el que el evento tuvo efecto. Usaremos ese dato para pasárselo a jQuery y referenciar ese elemento. De esa manera le agregamos la clase active.


La siguiente linea la desmontaremos:


jQuery('#' + jQuery(evt.target).attr('title')).addClass('active')


La clave reside aui:

jQuery(evt.target).attr('title')


Tomamos el atributo title del elemento sobre el que se hizo click y lo asociamos como un id con jQuery ('#' + jQuery(evt.target).attr('title')) que es lo que explicamos al inicio. Los titles de los li son iguales a los ids de los contenidos que se quieren mostrar y le agregamos la clase active.


Y listo. Ya lo tenemos.


VUEJS


Veamos ahora lo mismo con VueJs


Enlaces:


HTML:


<div class="container top20" id="app">

<div class="row">

<div class="tabulacion">

<ul class="tab" id="tab">

<li class="nav-option" :class="{active: option===item}" v-for="item in ['home', 'información', 'servicios', 'contacto']" :key="item" :title="item" @click="option=item">

{{item.charAt(0).toUpperCase() + item.slice(1)}}</li>

</ul>

<div>

<div class="nav-content" v-show="option==='home'">

Este es el contenido de home

</div>

<div class="nav-content" v-show="option==='información'">

Esta es la información

</div>

<div class="nav-content" v-show="option==='servicios'">

Estos son los servicios

</div>

<div class="nav-content" v-show="option==='contacto'">

Datos de contacto

</div>

</div>

</div>

</div>

</div>


En este ejemplo hemos cambiado la manera. Podríamos seguir usando la metodología de la clase active que usamos en jQuery pero he querido usar una característica conocida pero un poco olvidada de VueJS v-show.


Pero primero miremos los cambios hechos:


<li class="nav-option" :class="{active: option===item}" v-for="item in ['home', 'información', 'servicios', 'contacto']" :key="item" :title="item" @click="option=item">

{{item.charAt(0).toUpperCase() + item.slice(1)}}</li>


Lo primero es v-for. Otra característica nueva. Quienes ya hayan usado preprocesadores de HTML como Pug (anteriormente Jade) entenderán más rápidamente de que va la idea.


De todas maneras es bastante intuitiva la intención: repetir un elemento una cantidad X de veces.


v-for usa un único parámetro que marca la secuencia de inicio y de final. Se usa la semántica "item in array", hay variantes que iremos viendo poco a poco. Si hay más curiosidad se puede revisar su documentación: https://es.vuejs.org/v2/guide/list.html


En este caso hemos creado el array en el mismo v-for pero podría ser una variable. Solo que hemos pensado que si solo lo usaremos ahí no hay necesidad de crear una variable para este caso.

El v-for creará un elemento li por cada elemento del array (4). El atributo key (:key porque pasaremos una variable y no una cadena de texto directamente) le sirve a Vuejs para identificar de forma única cada elemento del v-for. Es lo único que pide ese parámetro: tener un valor único para cada elemento creado con el v-for


Volvemos a la lógica (no necesaria aquí pero por resolver como se haría en este caso) del title. Y se asocia :title con el valor de cada item.


Usaremos una variable llamada option. En el click le damos a option el valor del item en cada li creado.


En :class Le decimos que se le pase la clase active cuando option sea igual el item actual. O sea cuando se haga click.


Esto lo explicaremos un poco más:


{{item.charAt(0).toUpperCase() + item.slice(1)}}


JS tiene funciones del string para mayúsculas (uppercase) y minúsculas (lowercase) pero no para poner solo en mayúscula la primer letra de una palabra. Como podemos observar en el array todos los valores están en minúsculas pero los textos de las pestañas de la tabulación no quedarían bien así. Por lo que debemos convertir la primer letra de la cadena a mayúsculas y el resto mostrarlo tal cual.


item.charAt(0).toUpperCase()


Convierte la primer letra (charAt(0) ) del item en mayúsculas (toUpperCase()), el resto del texto se agrega con item.slice(1) que devuelve la cadena desde el segundo (1) carácter.


Y con esta parte se ha resuelto toda la lógica de elección de pestaña y de renderizado de las mismas. Veamos el código del contenido de nuevo:


<div>

<div class="nav-content" v-show="option==='home'">

Este es el contenido de home

</div>

<div class="nav-content" v-show="option==='información'">

Esta es la información

</div>

<div class="nav-content" v-show="option==='servicios'">

Estos son los servicios

</div>

<div class="nav-content" v-show="option==='contacto'">

Datos de contacto

</div>

</div>


Hablemos de v-show. Podíamos usar v-if perfectamente o incluso la misma lógica para la clase active que en los li pero hemos optado por v-show para hablar de esta característica de VueJs


Cuando hablamos de v-if decíamos que el elemento no se renderizaba y de esa manera no se entregaba al navegador ahorrándole tiempo y trabajo. Esto está bien en muchos casos. Sobre todo cuando se trabaja con una cantidad de datos determinados que necesitan mucho trabajo del navegador para mostrarlos correctamente. Por ejemplo un listado cuyas filas permitan ampliar los datos relacionados. Pero en muchos casos v-show es la opción adecuada. Simplemente oculta los elementos que no cumplen la condición. Al igual que v-if la condición debe tener una resolución lógica o sea TRUE o FALSE.


v-show no tiene un v-else pero si hiciera falta es fácil de solucionar:


<div v-show="valor">

<span>Verdadero</span>

<div>

<div v-show="!valor">

<span>Falso</span>

</div>


Volviendo al código. La condición es que option sea igual a una cadena de caracteres que coinciden con los valores del array del v-for de los li.


Tenemos todo resuelto así que el código JS es sencillo:


<script>

new Vue({

el: '#app',

data: {

option: 'home'

}

})

</script>


Simplemente definimos la variable option y le asignamos uno de los valores del array del v-for para que haya ya una opción y un contenido elegidos.


Enlaces Index:


Este post ha vuelto a ser más corto para no saturar. Se han conocido dos conceptos nuevos que seguiremos usando. Espero que haya sido útil.


Consultas, dudas, comentarios: Slack de PEUM o en Twitter.


No hay comentarios:

Publicar un comentario

Vuejs para programadores jQuery. Galería. Load More XVI

Vuejs para programadores jQuery. Galería. Load More XVI En el artículo de hoy vamos a tratar el tema de plugins de jQuery (crearemos dos) ...