Una introducción de Vue.js para personas que conocen lo suficiente jQuery para sobrevivir

El logo de Vue.js

He tenido una relación de amor y odio con JavaScript durante años.

Conocí el lenguaje a través del chico favorito de la comunidad de diseño y desarrollo, jQuery. Verá, en el momento en que comencé a aprender JavaScript, como "Diseñador que codifica", trabajar con jQuery fue una experiencia mágica. Podría hacer modales fadeIn y fadeOut. Con una biblioteca de terceros, podría agregar desplazamiento de paralaje a mi cartera con solo una llamada de función. Casi todo lo que podría haber soñado estaba encapsulado en un solo archivo de ~ 100 kb ...

Y luego salió Angular. No tuve más remedio que rehacer toda mi cartera con el marco. Y luego salió React. No tuve más remedio que rehacer todo mi portafolio con la biblioteca. Y entonces salió Vue.js. No tuve más remedio que rehacer todo mi portafolio con la biblioteca ... Ves a dónde va esto.

Dejando de lado todas las bromas, he disfrutado mucho perfeccionar mis habilidades de JavaScript a través de la construcción de cosas aquí y allá con estos diferentes marcos y bibliotecas. He leído innumerables artículos y tutoriales en el proceso, pero ninguno me ha atrapado más que la pieza de Shu Uesugi, "Introducción a React.js para personas que saben lo suficiente como para poder sobrevivir".

Shu lleva a los lectores, que se supone que tienen cierto nivel de competencia con los fundamentos de JavaScript y jQuery, en un viaje por el mundo de React mientras crean un clon del componente "componer tweet" de Twitter.

Este marco conceptual fue muy útil para mí como alguien que aprende mejor haciendo. De hecho, cada vez que sale una nueva biblioteca de JavaScript, me encuentro volviendo al ejemplo de este artículo para probar las aguas. Y entonces, me gustaría tomar prestado este marco mientras los paso a través de mi experiencia reciente de aprender Vue.

Antes de comenzar los pasos a continuación, le recomiendo que lea el artículo de Shu. Hace un trabajo fantástico al guiarte a través del código jQuery que podrías escribir para implementar algunas de estas características. Por lo tanto, y para mitigar el riesgo de redundancia, me centraré en mostrarle los entresijos de Vue.

Lo que estamos construyendo

La mayoría de nosotros tuiteamos (algunos más prolíficamente que otros). Por lo tanto, probablemente estamos familiarizados con el componente de interfaz de usuario en la captura de pantalla a continuación.

El cuadro

Lo creas o no, este componente de IU es un gran ejemplo de cómo Vue (y React, según Shu) podría mejorar tu vida como desarrollador de JavaScript / jQuery. Los elementos de este componente que nos enfocaremos en construir hoy son:

  • El

    3. Agregamos el atributo: disabled a nuestro botón. Los dos puntos anteriores deshabilitados denotan que nos gustaría evaluar el contenido dentro de las comillas como una expresión de JavaScript. Si omitiéramos los dos puntos, el contenido se trataría como una cadena. También notará que hemos agregado algunas líneas de CSS para darle al botón deshabilitado un estilo visual distinto.

     Tweet 
    ...
    botón [deshabilitado] {
      cursor: no permitido;
      opacidad: .5;
    }

    4. También agregamos una propiedad calculada en nuestra instancia llamada tweetIsEmpty. Tenga en cuenta que esta propiedad es en realidad una función que devuelve un valor booleano basado en la longitud del atributo de tweet de nuestro modelo de datos. Vue simplifica el acceso a su modelo de datos tanto en HTML (como se muestra arriba) como en la instancia misma. Gracias a la magia del enlace de datos bidireccional, esta función se evalúa cuando se actualiza el valor del tweet. Cuando la función se evalúa como verdadera, nuestro botón está deshabilitado y viceversa.

    tweetIsEmpty: function () {
      devuelve this.tweet.length === 0;
    }

    Es cierto que esto se sintió como humo y espejos cuando empecé con Vue. Lo que me ayudó fue ver literalmente lo que estaba sucediendo con nuestro modelo de datos bajo el capó mientras interactuaba con el componente. Como podemos acceder fácilmente a nuestro modelo de datos en nuestro HTML a través de la sintaxis de llaves antes mencionada, podemos construir un bucle de retroalimentación visual rápido. ¡Puntuación!

    El valor de tweet es: {{tweet}}

    El valor de tweetIsEmpty es: {{tweetIsEmpty}}

    Por favor, siéntase libre de repetir este paso si algo en el camino fue confuso (ya sea debido a mis malas habilidades de escritura o codificación, o debido a Vue). Envía un tweet o deja un comentario si tienes alguna pregunta en particular.

    Paso 3: Implemente la segunda característica: muestre el número de caracteres restantes

    Descripción de la función: a medida que el usuario escribe, muestra el número de caracteres restantes (de 140) en el tweet. Si un usuario ha ingresado más de 140 caracteres, desactive el botón azul Tweet.

    Hasta ahora hemos aprendido sobre el enlace de datos bidireccional y las propiedades calculadas, conceptos que están en el núcleo de Vue. Es nuestro día de suerte, porque podemos aprovechar estos conceptos para construir nuestra próxima característica: mostrar a los usuarios cuántos caracteres (de 140) quedan, y deshabilitar el botón si se eclipsa este límite.

    Una vez más, lo guiaré a través de los cambios de JavaScript y HTML necesarios para implementar esta función.

    En nuestro JavaScript, hemos hecho algunas cosas.

    1. Como medida de limpieza, enumeramos la longitud máxima de un tweet (140 caracteres) como una constante, MAX_TWEET_LENGTH.
    const MAX_TWEET_LENGTH = 140;

    2. Agregamos otra propiedad calculada, charactersRemaining, que devuelve dinámicamente la diferencia entre 140 y la longitud del tweet introducido por el usuario.

    caracteres restantes: función () {
      return MAX_TWEET_LENGTH - this.tweet.length;
    }

    3. Cambiamos el nombre de la antigua propiedad tweetIsEmpty a tweetIsOutOfRange y actualizamos la lógica de la función en consecuencia. Observe cómo estamos utilizando los caracteres calculados Propiedad restante para derivar este valor. ¡Hurra por la reutilización del código!

    tweetIsOutOfRange: function () {
      devuelve this.charactersRemaining == MAX_TWEET_LENGTH
          || this.charactersRemaining <0;
     }

    En el lado HTML de las cosas, solo tenemos que hacer algunos cambios, gracias al poder del enlace de datos bidireccional de Vue.

       {{charactersRemaining}}    Tweet

    Para los estudiantes visuales, mira la magia:

    Paso 4: Implemente la tercera característica: Estilo condicional del indicador "Caracteres restantes"

    Descripción de la característica: Al componer un Tweet, el color del indicador de "caracteres restantes" debe cambiar a rojo oscuro cuando solo quedan veinte caracteres, y rojo claro cuando quedan diez o menos.

    Manipular el estilo o la clase de un elemento puede ser engorroso con jQuery, y Vue ofrece una forma mucho más limpia de hacerlo. El enfoque de Vue se siente más declarativo, ya que usted describe cómo desea que cambie el estilo de algo (basado, por ejemplo, en un estado dado) y deja que Vue haga el trabajo pesado.

    En el contexto de esta función, nuestro indicador de "caracteres restantes" tiene dos de esos estados y una clase CSS correspondiente para cada uno.

    1. Cuando quedan entre diez y veinte caracteres, el indicador debe tener la clase rojo oscuro
    2. Cuando quedan menos de diez caracteres, el indicador debe tener la clase rojo claro

    A estas alturas, su cerebro Vue debería estar gritando "PROPIEDADES COMPUTARIAS". Así que, obliguemos a este cerebro y conectemos esas propiedades.

    underTwentyMark: function () {
      devuelve this.charactersRemaining <= 20
        && this.charactersRemaining> 10;
      },
    underTenMark: function () {
      devuelve this.charactersRemaining <= 10;
    }

    Con nuestra lógica en su lugar, echemos un vistazo a una de las formas en que Vue maneja el estilo condicional: la directiva v-bind: class. Esta directiva espera un objeto cuyas claves son clases CSS y cuyos valores son las propiedades calculadas correspondientes.

    {'rojo oscuro': underTwentyMark, 'rojo claro': underTenMark}

    Al agregar la directiva a la etiqueta span que encierra nuestro indicador de "caracteres restantes", hemos completado nuestra función.

    
      {{ caracteres restantes }}
    

    Bajo el capó, y gracias al enlace de datos bidireccional, Vue se encargará de la adición y eliminación de estas clases en función de las propiedades calculadas especificadas.

    Paso 5: Implemente la cuarta característica: "Adjuntar foto" UX

    Descripción de la función: permite a los usuarios adjuntar una sola foto a su tweet a través de un cuadro de diálogo de selección de archivos. Cuando la foto se haya cargado, muéstrela debajo del área de texto y permita que los usuarios eliminen el archivo adjunto haciendo clic en la imagen

    Advertencia justa: están sucediendo muchas cosas en esta sección. La belleza es que, a pesar de que esta característica agrega una funcionalidad considerable, no tendremos que escribir tanto código. Entonces, comencemos dividiendo el diseño de interacción en pasos.

    1. El usuario hace clic en el botón "Agregar foto"
    2. El usuario ve un cuadro de diálogo de selección de archivos y puede seleccionar una foto para cargar
    3. Al seleccionar la foto, aparece un cuadro debajo del área de texto con la foto seleccionada dentro
    4. El usuario hace clic en el botón circular X para eliminar la foto.
    5. El usuario ve el estado inicial del paso 1

    Hasta este momento, aún no hemos realizado ningún manejo de eventos (escuchando clics de botones, cambios de entrada, etc.). Como es de esperar, Vue facilita el manejo de tales eventos al proporcionarnos la directiva v-on (@ para abreviar). Al pasar un método como valor de esta directiva, podemos escuchar efectivamente los eventos DOM y ejecutar JavaScript cuando se activan.

    Antes de sumergirse en nuestro trabajo de características, practique algo rápido.

    El manejo de eventos es tan fácil como agregar la directiva @click a un botón dado y agregar un método correspondiente a la clave de métodos en nuestra instancia de Vue.

    
    ...
    métodos: {
      logNameToConsole: function () {
        if (this.name! == 'Donald Trump') {
          console.log (this.name);
        } más {
          console.warn ('Lo siento, no entiendo');
        }
      },
    }

    Volver a nuestro trabajo de características ... En este paso, nuestro marcado y JavaScript han cambiado de las siguientes maneras:

    1. Agregamos un botón con una directiva @click. Cuando un usuario hace clic en este botón, se llamará al método triggerFileUpload.

    Entonces, en nuestro JavaScript, agreguemos una clave de métodos a nuestra instancia de Vue con dicho método dentro, así como un atributo de datos para nuestra foto.

    datos: {
     foto: nulo
    },
    calculado: {},
    métodos: {
      triggerFileUpload: function () {
        esto. $ refs.photoUpload.click (); // ¿LOLWUT?
      },
    }

    2. Es notoriamente difícil diseñar las entradas de archivos HTML5. Una solución alternativa consiste en poner una entrada en el DOM y ocultarlo con CSS. Para que el navegador abra el selector de archivos nativo, se debe hacer clic en esta entrada. Sin embargo, la forma en que se hace clic y la forma en que el cliente maneja lo que el usuario carga es algo diferente.

    En nuestro marcado, hemos agregado una entrada de este tipo y la hemos ocultado con una clase especial de ocultación. También hemos agregado algunos otros atributos que vale la pena mencionar:

    • El atributo ref se usa para registrar una referencia a un elemento DOM dado. Dada esta referencia, podemos acceder al elemento DOM en nuestro código JavaScript con esto. $ Refs.photoUpload. Lo que significa que podemos activar programáticamente un evento click () en este elemento, evitando así el desafío descrito anteriormente.
    • Hacer clic en la entrada es una cosa; manejar el archivo que el usuario carga es otro. Afortunadamente, Vue nos permite adjuntar un controlador al evento de cambio de entrada a través de la directiva @change. El método que pasamos a esta directiva se invocará después de que un usuario seleccione un archivo del selector de archivos. Ese método, handlePhotoUpload, es bastante sencillo
    handlePhotoUpload: función (e) {
      var self = esto;
      lector var = nuevo FileReader ();
          
      reader.onload = function (e) {
        // Establezca esa cadena base 64 en la clave 'foto' de nuestro modelo de datos
        self.photo = (e.target.result);
      }
      // Leer archivo de carga como cadena base 64
      reader.readAsDataURL (e.target.files [0]);
     }

    ¡Respira hondo, porque casi hemos terminado con esta función!

    Una vez que un usuario ha subido una foto, debemos mostrar un cuadro debajo del área de texto con la foto seleccionada dentro. Así como el estilo condicional de los elementos es muy sencillo con Vue, también lo es la representación condicional o la visualización de elementos. Notará que en nuestro HTML, hemos agregado el siguiente marcado debajo del área de texto.

                   

    Vue ofrece un puñado de ayudantes de plantilla (v-if, v-show, v-else, etc.) para ayudarlo a mostrar y ocultar contenido condicionalmente. Cuando la expresión de JavaScript que se pasa a esta directiva se evalúa como verdadera, el elemento se representa y viceversa.

    En nuestro caso, agregamos una instrucción v-if que evalúa la propiedad calculada photoHasBeenUploaded.

    photoHasBeenUploaded: function () {
      devuelve this.photo! == null;
    }

    Cuando esa función se evalúa como verdadera, cuando la clave de foto de nuestro modelo de datos no es igual a nula, se procesa todo el div. Voilà!

    Y dentro de ese div representamos dos elementos:

    1. La imagen que se adjuntó, al pasar el contenido de la clave de la foto de nuestro modelo de datos a la directiva v-bind: src de Vue
    2. Un botón de eliminación que presenta otro ejemplo del controlador @ click, este en particular invoca una función que "elimina" la foto al configurar la clave de foto de nuestro modelo de datos como nula.
    removePhoto: function () {
      this.photo = nulo;
    }

    Estamos casi alli.

    Paso 6: Corrección, el usuario puede adjuntar "fotos"

    Entonces, podemos manejar efectivamente a un usuario adjuntando una foto al Tweet, pero ¿qué pasa si le gustaría subir muchas fotos?

    A estas alturas, debería estar pensando algo en el sentido de: "Creo que el único cambio significativo aquí es poder mostrar varias imágenes en ese cuadro que aparece condicionalmente debajo del área de texto, teniendo en cuenta que ya hemos conectado nuestros controladores de eventos ..." ¡estás en lo correcto! Echemos un vistazo a los pasos que debemos seguir

    1. Necesitamos actualizar nuestro modelo de datos cambiando la foto a fotos, la nueva clave es una matriz de cadenas base64 (no una sola cadena base64)
    datos: {
      fotos: []
    },

    2. Necesitamos actualizar nuestra propiedad calculada photoHasBeenUploaded para verificar la longitud de nuestra nueva clave de fotos, que ahora es una matriz.

    photoHasBeenUploaded: function () {
      devuelve this.photos.length> 0;
    }

    3. Necesitamos actualizar nuestro controlador input @change para recorrer los archivos cargados y empujarlos a nuestra tecla de fotos.

    handlePhotoUpload: función (e) {
      var self = esto;
      archivos var = e.target.files;
      for (let i = 0; i 
        reader.onloadend = function (evt) {
          self.photos.push (evt.target.result);
        }
        reader.readAsDataURL (archivos [i]);
      }
    },

    En el lado HTML, sin embargo, debemos embarcarnos en un nuevo territorio. Iterar sobre datos y renderizar contenido con jQuery puede ser engorroso.

    var matriz = [1, 2, 3, 4, 5];
    var newHTML = [];
    for (var i = 0; i ' + array [i] + '');
    }
    $ (". element"). html (newHTML.join (""));

    Afortunadamente, Vue ofrece una abstracción sobre este procedimiento a través de la directiva v-for. Esta directiva espera que proporcione una expresión en forma de (cosa, índice) en collectionOfThings, donde collectionOfThings es la matriz fuente, cosa es un alias para el elemento de la matriz que se está iterando, e index es, bueno, el índice de ese elemento .

    Un ejemplo prototípico podría verse así:

    Donde antes teníamos un elemento de figura singular para la foto cargada por el usuario, ahora tendremos N etiquetas de figura correspondientes a la longitud de la matriz fuente de fotos.

    Por suerte para nosotros, nuestro marcado no tiene que cambiar drásticamente, ya que la estructura general del diseño sigue siendo la misma.

         

    El único cambio que necesitamos hacer gira en torno al método removePhoto que, antes, establece la clave de foto singular en nuestro modelo de datos en nulo. Ahora, dado que tenemos N número de fotos, debemos pasar el índice del elemento al método removePhoto y extraer ese elemento de la matriz.

    removePhoto: function (index) {
      this.photos.splice (índice, 1);
    }

    Paso 7: Animación + Crédito extra

    En la interfaz de usuario de Twitter, el componente "Redactar Tweet" se abre de forma modal. Para nuestro gran final, me gustaría aplicar todas las técnicas de Vue que hemos aprendido hasta ahora e introducir una más: las transiciones.

    Ciclo de vida de transición

    Una palabra de precaución, las transiciones son un tema vasto en la tierra Vue. Vamos a examinar e implementar una pequeña porción de esta funcionalidad, es decir, integrar una biblioteca de animación de terceros, Velocity JS, con Vue.

    En pocas palabras, Vue proporciona un componente de transición que le permite agregar animaciones de entrada / salida para el elemento contenido, siempre que el elemento esté configurado para mostrarse condicionalmente a través de, por ejemplo, una directiva v-if o v-show.

    
        
               

    En nuestro ejemplo, hemos adjuntado dos métodos que se corresponden con dos eventos en el ciclo de vida de la transición: v-on: enter y v-on: leave. Por lo tanto, hemos agregado estas definiciones de métodos a nuestra instancia de Vue, difiriendo a Velocity JS para atenuar nuestro modal dentro y fuera.

    métodos: {
      modalEnter: function (el, done) {
        Velocidad (el, 'fadeIn', {duración: 300, completa: hecho, pantalla: 'flex'})
      },
      modalLeave: function (el, done) {
        Velocidad (el, 'fadeOut', {duración: 300, completa: hecho})
      }
    }

    Como se mencionó anteriormente, la transición se activará cuando el elemento contenido dentro se configure condicionalmente para mostrar. Entonces, en el div interno de nuestro componente de transición, hemos agregado una declaración v-if cuyo valor es un booleano modalShowing. Actualicemos el modelo de datos de nuestra instancia en consecuencia.

    datos: {
      modalShowing: falso
    }

    Ahora, cuando queremos mostrar el modal, ¡todo lo que tenemos que hacer es establecer ese booleano en verdadero!

    Y escribe un método para que coincida.

    hideModal: function () {
      this.modalShowing = false;
    },
    showModal: function () {
      this.modalShowing = true;
    },

    Con algunos trucos de CSS, también hemos adjuntado un controlador de eventos de clic al fondo, para que los usuarios puedan ocultar el modal. ¡Puntuación!

    Conclusión

    Bueno, espero que no haya sido demasiado doloroso (y que hayas aprendido una o dos cosas en el camino). Solo echamos un vistazo a una pequeña porción de lo que Vue tiene para ofrecer, aunque, como se mencionó anteriormente, estos conceptos son cruciales para desbloquear el potencial de Vue.

    Admito que es injusto comparar Vue con jQuery. Son productos de diferentes épocas, con casos de uso bastante diferentes. Sin embargo, para aquellos que han tenido dificultades para aprender la manipulación del DOM y el manejo de eventos a través de jQuery, espero que estos conceptos sean un soplo de aire fresco que pueda aplicar a su flujo de trabajo.