Cómo la API de composición de Vue reemplaza a Vue Mixins

Índice
  1. Mixins en pocas palabras
  2. Los mixins se consideran “dañinos”
  3. Migrando desde mixins
  4. Curso intensivo de API de composición
  5. extraccion de codigo
  6. Reutilización de código
  7. Colisiones de nombres… ¡resueltas!
  8. Dependencias implícitas… ¡resueltas!
  9. terminando

¿Quiere compartir código entre sus componentes de Vue? Si está familiarizado con Vue 2, probablemente haya utilizado un mixin para este propósito. Pero la nueva API de composición, que ahora está disponible como complemento para Vue 2 y una característica próxima de Vue 3, proporciona una solución mucho mejor.

En este artículo, veremos los inconvenientes de los mixins y veremos cómo la API de la composición supera y permite que las aplicaciones Vue sean mucho más escalables.

Mixins en pocas palabras

Repasemos rápidamente el patrón de mixins, ya que es importante tenerlo presente para lo que cubriremos en las siguientes secciones.

Normalmente, un componente de Vue se define mediante un objeto JavaScript con varias propiedades que representan la funcionalidad que necesitamos, como data, methods, computedetc.

// MyComponent.jsexport default {  data: () = ({    myDataProperty: null  }),  methods: {    myMethod () { ... }  }  // ...}

Cuando queremos compartir las mismas propiedades entre componentes, podemos extraer las propiedades comunes en un módulo separado:

// MyMixin.jsexport default {  data: () = ({    mySharedDataProperty: null  }),  methods: {    mySharedMethod () { ... }  }}

Ahora podemos agregar esta mezcla a cualquier componente del consumidor asignándolo a la mixinpropiedad de configuración. En el tiempo de ejecución, Vue fusionará las propiedades del componente con cualquier mixin agregado.

// ConsumingComponent.jsimport MyMixin from "./MyMixin.js";
export default {  mixins: [MyMixin],  data: () = ({    myLocalDataProperty: null  }),  methods: {    myLocalMethod () { ... }  }}

Para este ejemplo específico, la definición de componente utilizado en el tiempo de ejecución tendría este aspecto:

export default {  data: () = ({    mySharedDataProperty: null    myLocalDataProperty: null  }),  methods: {    mySharedMethod () { ... },    myLocalMethod () { ... }  }}

Los mixins se consideran “dañinos”

A mediados de 2016, Dan Abramov escribió “Mixins Considered Harmful” en el que sostiene que el uso de mixins para reutilizar la lógica en los componentes de React es un antipatrón y, en cambio, aboga por alejarse de ellos.

Desafortunadamente, los mismos inconvenientes que mencionamos sobre los mixins de React también se aplican a Vue. Familiarícenos con estos inconvenientes antes de ver cómo los supera la API de composición.

colisiones de nombres

Vimos cómo el patrón mezcla fusionando dos objetos en tiempo de ejecución. ¿Qué pasa si ambos comparten una propiedad con el mismo nombre?

const mixin = {  data: () = ({    myProp: null  })}
export default {  mixins: [mixin],  data: () = ({    // same name!    myProp: null  })}

Aquí es donde entra en juego la estrategia de fusión. Este es el conjunto de reglas para determinar qué sucede cuando un componente contiene múltiples opciones con el mismo nombre.

La estrategia de combinación predeterminada (pero opcionalmente configurable) para los componentes de Vue dicta que las opciones locales anularán las opciones de combinación. Aunque hay excepciones. Por ejemplo, si tenemos varios ganchos de ciclo de vida del mismo tipo, estos se agregarán a una matriz de ganchos y todos se llamarán secuencialmente.

Aunque no deberíamos encontrarnos con ningún error real, se vuelve cada vez más difícil escribir código cuando se hacen malabarismos con propiedades con nombre en Múltiples componentes y mixins. Es especialmente difícil una vez que se agregan mixins de terceros como paquetes npm con sus propias propiedades con nombre que pueden causar conflictos.

Dependencias implícitas

No existe una relación jerárquica entre un mixin y un componente que lo consume. Esto significa que un componente puede usar una propiedad de datos definida en el mixin (por ejemplo mySharedDataProperty), pero un mixin también puede usar una propiedad de datos que supone que está definida en el componente (por ejemplo myLocalDataProperty). Este suele ser el caso cuando se utiliza un mixin para compartir la validación de entrada. El mixin podría esperar que un componente tenga un valor de entrada que usaría en su propio método de validación.

Sin embargo, esto puede causar problemas. ¿Qué sucede si queremos refactorizar un componente más adelante y cambiar el nombre de una variable que necesita el mixin? Al observar el componente, no nos daremos cuenta de que algo anda mal. Una linter tampoco lo recogerá. Sólo veremos el error en el tiempo de ejecución.

Ahora imagina un componente con un montón de mixins. ¿Podemos refactorizar una propiedad de datos local o romperá un mixin? ¿Qué mezcla? Tendríamos que buscarlos todos manualmente para saberlo.

Migrando desde mixins

El artículo de Dan ofrece alternativas a los mixins, incluidos componentes de orden superior, métodos de utilidad y algunos otros patrones de composición de componentes.

Si bien Vue es similar a React en muchos aspectos, los patrones alternativos que sugieren no se traducen bien en Vue. Entonces, a pesar de que este artículo se escribió a mediados de 2016, los desarrolladores de Vue han estado sufriendo problemas de mezcla desde entonces.

Hasta ahora. Los inconvenientes de los mixins fueron uno de los principales factores motivadores detrás de la API de composición. Veamos una descripción general rápida de cómo funciona antes de ver cómo supera los problemas con los mixins.

Curso intensivo de API de composición

La idea clave de la API de composición es que, en lugar de definir la funcionalidad de un componente (por ejemplo, estado, métodos, propiedades calculadas, etc.) como propiedades de objeto, las definimos como variables de JavaScript que se devuelven desde una nueva setupfunción.

Tomemos este ejemplo clásico de un componente de Vue 2 que define una función de “contador”:

//Counter.vueexport default {  data: () = ({    count: 0  }),  methods: {    increment() {      this.count++;    }  },  computed: {    double () {      return this.count * 2;    }  }}

Lo que sigue es exactamente el mismo componente definido usando la API de composición.

// Counter.vueimport { ref, computed } from "vue";
export default {  setup() {    const count = ref(0);    const double = computed(() = count.value * 2)    function increment() {      count.value++;    }    return {      count,      double,      increment    }  }}

Primero notarás que importamos una reffunción, lo que nos permite definir una variable reactiva que funciona prácticamente igual que una datavariable. La misma historia para la función calculada.

El incrementmétodo no es reactivo, por lo que puede declararse como una función simple de JavaScript. Observe que necesitamos cambiar la subpropiedad valuepara cambiar el valor de la countvariable reactiva. Esto se debe a que las variables reactivas creadas usando refdeben ser objetos para conservar su reactividad a medida que se transmiten.

Es una buena idea consultar los documentos de la API de Vue Composition para obtener una explicación detallada de cómo funciona la referencia.

Una vez que hemos definido estas características, las pasamos desde la función de configuración. No hay diferencia en la funcionalidad entre los dos componentes anteriores. Todo lo que hicimos fue usar la API alternativa.

Consejo: la API de composición será una característica principal de Vue 3, pero también puedes usarla en Vue 2 con el complemento NPM @vue/composition-api.

extraccion de codigo

La primera clara de la API de composición es que es fácil extraer lógica de ventaja.

Refactorizamos el componente definido anteriormente con la API de composición para que las características que definimos estén en un módulo de JavaScript useCounter. (Prefijar la descripción de una característica con “uso” es una convención de nomenclatura de la API de composición).

// useCounter.jsimport { ref, computed } from "vue";
export default function () {  const count = ref(0);  const double = computed(() = count.value * 2)  function increment() {    count.value++;  }  return {    count,    double,    increment  }}

Reutilización de código

Para consumir esa característica en un componente, simplemente importamos el módulo al archivo del componente y lo llamamos (teniendo en cuenta que la importación es una función). Esto devuelve las variables que definimos y posteriormente podemos devolverlas desde la función de configuración.

// MyComponent.jsimport useCounter from "./useCounter.js";export default {  setup() {    const { count, double, increment } = useCounter();    return {      count,      double,      increment    }  }}

Todo esto puede parecer un poco detallado y sin sentido al principio, pero veamos cómo este patrón supera los problemas con los mixins que vimos anteriormente.

Colisiones de nombres… ¡resueltas!

Vimos antes cómo un mixin puede usar propiedades que pueden tener el mismo nombre que las del componente consumidor, o incluso más insidiosamente, en otros mixins usados ​​por el componente consumidor.

Esto no es un problema con la API de composición porque necesitamos nombrar explícitamente cualquier estado o método devuelto por una función de composición:

export default {  setup () {    const { someVar1, someMethod1 } = useCompFunction1();    const { someVar2, someMethod2 } = useCompFunction2();    return {      someVar1,      someMethod1,      someVar2,      someMethod2    }  }}

Las colisiones de nombres se resolverán de la misma manera que para cualquier otra variable de JavaScript.

Dependencias implícitas… ¡resueltas!

También vimos antes cómo un mixin puede usar propiedades de datos definidas en el componente consumidor, lo que puede hacer que el código sea frágil y muy difícil de razonar.

Una función de composición también puede invocar una variable local definida en el componente consumidor. Sin embargo, la diferencia es que esta variable ahora debe pasarse explícitamente a la función de composición.

import useCompFunction from "./useCompFunction";
export default {  setup () {    // some local value the a composition function needs to use    const myLocalVal = ref(0);
    // it must be explicitly passed as an argument    const { ... } = useCompFunction(myLocalVal);  }}

terminando

El patrón mixin parece bastante seguro en la superficie. Sin embargo, compartir código mediante la fusión de objetos se convierte en un antipatrón debido a la fragilidad que agrega al código y la forma en que oscurece la capacidad de razonar sobre la funcionalidad.

La parte más inteligente de la API de composición es que permite a Vue aprovechar las salvaguardas integradas en JavaScript nativo para compartir código, como variables a funciones y el sistema de pasar módulos.

¿Eso significa que la API de composición es superior en todos los sentidos a la API clásica de Vue? No. En la mayoría de los casos, podrás seguir con la API clásica. Pero si planea reutilizar el código, la API de composición es indiscutiblemente superior.

SUSCRÍBETE A NUESTRO BOLETÍN 
No te pierdas de nuestro contenido ni de ninguna de nuestras guías para que puedas avanzar en los juegos que más te gustan.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Subir

Este sitio web utiliza cookies para mejorar tu experiencia mientras navegas por él. Este sitio web utiliza cookies para mejorar tu experiencia de usuario. Al continuar navegando, aceptas su uso. Mas informacion