Video Summary and Transcription
La charla discute las recientes actualizaciones de características en Vue 3.3, centrándose en la configuración de scripts y el soporte de TypeScript. Cubre mejoras en la definición de props utilizando tipos importados y soporte de tipos complejos. La introducción de componentes genéricos y firmas reelaboradas para componentes definidos proporciona más flexibilidad y mejor soporte de tipo. Otras características incluyen la inferencia automática de props en tiempo de ejecución, mejor define emite y slots definidos, y características experimentales como la destrucción de props reactivas y define modelo. La charla también menciona planes futuros para Vue, incluyendo la estabilización de suspense y la mejora de las invalidaciones de computadora.
1. Introducción a Vue 3.3 y soporte de TypeScript
¡Hola, Reino Unido! Hoy, voy a hablar sobre la reciente actualización de características en Vue 3.3. El enfoque fue mejorar la experiencia de desarrollo con script setup y TypeScript. Vue inicialmente no soportaba TypeScript, pero a medida que la base de usuarios creció, repensamos partes del marco para acomodar aplicaciones complejas. Un buen soporte de TypeScript mejora la productividad entre equipos y la mantenibilidad a largo plazo.
¡Hola, Reino Unido! Así que es mi primera vez en el Reino Unido, primera vez en Londres, ¡súper emocionado de estar aquí! Tuvimos un tour en autobús ayer, realmente no tuve mucha oportunidad de caminar por mí mismo todavía, pero ha sido una experiencia muy reveladora, mucha historia aquí, así que súper emocionado y súper emocionado de conectar con todos los desarrolladores de aquí, y también de ¡de todas partes de donde vengan!
Así que hoy, voy a hablar sobre la actualización de características que está ocurriendo recientemente en Vue, y en caso de que aún no lo sepan, Vue 3.3 fue lanzado ayer. Así que esta fue la primera versión menor en mucho tiempo, así que 3.2 fue lanzado hace más de un año, y una de las razones de eso fue porque pasamos mucho tiempo trabajando en Vite y otros proyectos relacionados. Invertimos mucho tiempo en, digamos, el lado de las IDE, haciendo las herramientas de lenguaje, Volar y todo, iluminando toda la experiencia de desarrollo alrededor de la herramienta ecosistema alrededor del núcleo de Vue. Pero ahora estamos moviendo nuestra atención de nuevo al núcleo de Vue, y van a ver más lanzamientos frecuentes del núcleo de Vue después de este. Así que este es el comienzo de muchas cosas nuevas que están por venir. Así que echemos un vistazo al 3.3.
El enfoque de esta versión fue, de nuevo, mejorar la experiencia de desarrollo cuando estás usando script setup en componentes de archivo único y TypeScript. Ahora, no te enfades conmigo si no usas TypeScript. Creo que, obviamente, cuando Vue empezó no soportábamos TypeScript. De hecho, muchas de las APIs iniciales ni siquiera fueron diseñadas con TypeScript en mente. Así que, con el tiempo, tuvimos que repensar lentamente partes del marco para pensar en, oh, ¿cómo funciona esta API con TypeScript? Cuando introducimos nuevas APIs, ¿cómo funcionarán estas nuevas APIs con TypeScript? Y la razón de eso es porque en las etapas iniciales cuando Vue era relativamente pequeño, nuestra base de usuarios estaba enfocada principalmente en casos de uso relativamente simples. Estaban usando en gran medida un marco de back-end y sólo querían una interactividad simple en el front-end. Pero hoy en día, nuestro caso de uso se ha expandido enormemente y la gente está construyendo aplicaciones realmente complejas con Vue. Y en situaciones como esa, cuando tienes grandes proyectos, grandes equipos, mucha gente trabajando juntos con diferentes niveles de experiencia, tener un sistema de tipos y tener una buena experiencia de desarrollo con TypeScript te va a ayudar mucho con la productividad entre equipos y la mantenibilidad a largo plazo de tus aplicaciones. Así que creemos que esto es algo realmente importante que queremos clavar, y ha habido históricamente algunos puntos de dolor en Vue cuando estás usando Vue con TypeScript, que creemos que hemos resuelto en gran medida en esta versión.
2. Tipos Importados para Definir Props
Desde la introducción de Script Setup, una de las características más deseadas en Vue 3.2 es la capacidad de usar tipos importados al definir props. El compilador de Vue analiza los tipos proporcionados para definir props y determina las props que el componente espera en tiempo de ejecución. El compilador genera la lista correcta de props en tiempo de ejecución, asegurando que la aplicación funcione.
Probablemente una de las características más deseadas desde 3.2, desde la introducción de Script Setup es la capacidad de usar tipos importados al definir props. Este ejemplo aquí realmente funcionó en 3.2 cuando importas un tipo de otro archivo y lo usas en DefineProps con la sintaxis de declaración de tipo.
Algunos antecedentes aquí, la razón por la que necesitamos hacer algo especial con los tipos aquí es porque en tiempo de ejecución, un componente de Vue necesita saber la lista explícita de props que se espera que reciba. Así que sin esa información no podrá decir si algo que recibe debería ser tratado como una prop versus simplemente un atributo de paso.
Esta es la razón por la que el compilador de Vue necesita mirar los tipos que proporcionaste para definir props, y luego intentar analizar qué props espera recibir este componente en tiempo de ejecución. Aquí, sólo con mirar la sintaxis, te darás cuenta de que es muy fácil determinar que message msg es lo único que este componente espera. Es determinista, así que el compilador dice, OK, ya he descubierto que message va a ser una prop esperada. Incluso si no soy capaz de inferir completamente lo que es este tipo externo, no me impide generar la lista correcta de props en tiempo de ejecución, para que tu aplicación simplemente funcione, ¿verdad? Porque en producción, realmente no hacemos validación de props en tiempo de ejecución basada en estos tipos aquí.
3. Tipos Importados y Soporte de Tipos Complejos
En Vue 3.2, el compilador carecía de la capacidad de mirar dentro de los tipos importados. Sin embargo, en 3.2, logramos soportar la mayoría de los casos comunes. Utilizamos la API de TypeScript para la resolución de módulos y analizamos los archivos para generar la información de tipo correcta. Todavía hay limitaciones, especialmente para tipos complejos, pero para el código a nivel de aplicación, cubre la mayoría de los casos. Estamos trabajando con los autores de las bibliotecas de componentes para mejorar su experiencia de autoría y soportar sus casos especiales.
Pero las cosas se complican un poco cuando, digamos, usas una interfaz importada, y luego simplemente la pasas a definir props de esta manera. Ahora, en 3.2, el compilador no era capaz de mirar realmente qué hay dentro de este tipo, porque hasta 3.2, la compilación de componentes de Vue siempre es de contexto de un solo archivo, lo que significa que el compilador sólo ve este archivo. Así que no tiene ninguna información sobre otros archivos, porque no tiene la información sobre tu sistema de archivos, sobre tu configuración de alias, o la configuración de ruta en tu tsconfig. Así que si queremos realmente resolver este tipo y mirar qué propiedades están incluidas en él, el compilador realmente necesita resolver este especificador de importación. Esencialmente necesita saber en qué archivo estamos, resolver la ruta relativa, y luego también necesitamos tener en cuenta, digamos, si estás importando un tipo de un paquete npm, ¿cómo resolvemos ese archivo de paquete npm? Y ¿cómo, digamos, si el usuario ha configurado mapeos de ruta personalizados en tsconfig, puedes tener un alias aleatorio aquí que apunta a cualquier archivo en tu sistema de archivos, y necesitaremos resolverlo de la misma manera que TypeScript resuelve los tipos. Así que suena como una tarea bastante desalentadora. Y para ser honestos, realmente nos llevó bastante esfuerzo hacer que esto funcionara, pero en 3.2 hemos logrado soportar la mayoría de los casos comunes con los que te puedes encontrar. Por ejemplo, cuando estás usando una importación relativa, es relativamente simple porque nosotros conocemos la ruta del archivo del componente actual, así que podemos usar esta ruta relativa para buscar el otro archivo. Y luego necesitamos manejar la caché y la invalidación de archivos cuando editas esos archivos, y luego también necesitamos manejar los casos en los que estás importando desde un alias o un paquete npm, así que en realidad usamos la propia API de TypeScript para hacer la resolución de módulos para obtener el mismo archivo exacto al que TypeScript está resolviendo, y luego analizamos ese archivo para obtener la información de tipo correcta con el fin de generar el code de tiempo de ejecución que utilizas. Así que parece una característica simple, pero de hecho es bastante complicada y nos llevó bastante tiempo averiguar cómo hacerlo. Pero incluso con esto, todavía hay algunas limitaciones de las que tenemos que ser transparentes, no sólo los tipos importados, sino que también añadimos soporte para un conjunto limitado de tipos complejos. Por ejemplo, aquí estamos usando un tipo importado junto con un tipo de intersección con algunas props adicionales que podrías querer añadir a esta interfaz. También podemos hacer extensión de interfaz, o a veces puedes usar tipos de utilidad como requerido o opcional, tipos de utilidad incorporados como esos. Así que intentamos tener en cuenta estos tipos tanto como sea posible. Por ejemplo, este ejemplo aquí funcionará, porque somos capaces de resolver lo que sea que esté en las props, somos capaces de resolver lo que sea que esté aquí, y somos capaces de simplemente fusionar ambos. Pero finalmente todo el proceso de análisis sigue siendo basado en AST, no estamos usando realmente TypeScript en sí mismo para hacer toda la inferencia de tipo y todo, porque eso sería realmente costoso. Es una especie de enfoque pragmático donde intentamos soportar tanto como podamos simplemente analizando el AST, por lo que no será capaz de cubrir el 100% de los tipos, así que si tienes tipos complejos locos con tipos condicionales, inferencia condicional, o tipos mapeados locos con genéricos y todo, algunos de ellos no serán realmente totalmente soportados. Pero para los casos más comunes, esto probablemente va a cubrir la mayoría de los casos con los que te encontrarías en el code a nivel de aplicación. Así que los casos de tipo advanced suelen ocurrir cuando estás escribiendo una biblioteca de componentes relativamente advanced, y todavía estamos trabajando con los autores de las bibliotecas de componentes para averiguar qué casos especiales pueden necesitar para que podamos mejorar la experiencia de autoría para ellos y también los consumidores de esas bibliotecas de componentes. Así que esta va a seguir siendo un área en la que vamos a seguir invirtiendo.
4. Componentes Genéricos y Componentes Definidos
La siguiente gran característica en Vue 3.3 son los componentes genéricos, que te permiten expresar el tipo de elementos seleccionados en un componente de lista. Puedes usar genéricos, similar a TypeScript, para definir los parámetros de tipo y las restricciones. También introdujimos una firma redefinida para los componentes definidos, permitiendo a los autores de bibliotecas usar genéricos directamente. Esto proporciona más flexibilidad y mejor soporte de tipo al escribir componentes complejos con JSX o TSX.
La siguiente gran característica que habilitamos son los componentos genéricos. Así que si no estás familiarizado con TypeScript o los genéricos, piensa en ello como un... Usemos este componente como ejemplo. Así que estás construyendo un componente de lista. Este componente de lista va a recibir una lista de elementos, y también va a recibir ese elemento que está seleccionado. Así que a nivel de tipo, quieres decir que el elemento seleccionado va a tener el mismo tipo que el elemento en esa lista. Así que aquí, el problema es, no sé qué tipo exacto va a ser.
Así que los genéricos te permiten expresar eso. Así que aquí, simplemente vamos a añadir el atributo genérico a nuestra etiqueta de script aquí. Así que esto va a ser exactamente lo mismo que cuando estás usando genéricos normales en TypeScript, tienes este corchete angular, y pones los parámetros de tipo genérico en él. Así que puedes poner cualquier cosa que puedas poner en esos corchetes cuadrados aquí. Y vas a decir, simplemente vamos a tener un tipo genérico, T, y voy a aceptar una lista de elementos que va a ser un array de T y un elemento seleccionado, que es va a ser T. Así que como dije, puedes hacer cualquier cosa que funcionaría con genéricos normales, lo que significa que puedes tener estas restricciones de extensión, diciendo que este T necesita satisfacer esta restricción de tipo. O puedes tener múltiples parámetros de tipo, y luego puedes usarlos juntos. Así que este es sólo un ejemplo realmente forzado. No trates de darle demasiado sentido. Esto es sólo para demostrar la posibilidad de la sintaxis. Así que cualquier cosa que puedas hacer con genéricos normales en TypeScript, deberías ser capaz de expresar aquí.
Y también enviamos una especie de cosa medio horneada sobre componentes genéricos con componentes definidos. Así que esto está más orientado hacia los autores de bibliotecas, porque si has usado Vue, sabes que Vue puede trabajar realmente con JSX, y también puedes usar TSX con Vue. Y esto es, en algunas situaciones, preferido por los autores de bibliotecas cuando escriben realmente componentes complejos y dinámicos para que los consumas. Esto les da un poco más de flexibilidad, pero también se encuentran con la situación en la que necesitan genéricos, y anteriormente simplemente no había manera de hacer eso. O tenían que recurrir a trucos realmente complejos, trucos de tipo para poder expresar estas cosas. Así que redefinimos la firma de los componentes definidos para permitirte pasar directamente una función con genéricos al componente definido. Y funciona un poco como los componentes de función de React, con la diferencia de que, en lugar de devolver directamente JSX o una función de renderizado, o nodos virtuales, quieres devolver una función que devuelve JSX. Así que la diferencia entre esto y los hooks de React, si has usado React, obviamente sabrías que la diferencia aquí es que Composition API code se ejecuta sólo una vez cuando se crea un componente. No se llama repetidamente, sin embargo esta función de retorno aquí, la función de renderizado, sí se llama repetidamente. Esa es la razón por la que necesito separarlos, pero esto te da un compromiso bastante agradable entre ser capaz de usar el sistema de reactivity de Vue, con TSX, JSX, o funciones de renderizado manuales, junto con un soporte de tipo muy satisfactorio, con genéricos. Una cosa que falta aquí es que necesitamos proporcionar la misma generación de lista de props de tiempo de ejecución basada en tu soporte de tipos. Aquí está lo que hay que hacer aquí.
5. Inferencia Automática de Props en Tiempo de Ejecución
Estamos desarrollando un plugin de Babel para inferir automáticamente la lista de props en tiempo de ejecución e inyectarla en los componentes. Esto eliminará la necesidad de dobles declaraciones manuales y de ingeniería inversa en las bibliotecas de componentes. Nuestro objetivo a largo plazo es permitir a los usuarios de TypeScript centrarse únicamente en los tipos sin preocuparse por la lista de props en tiempo de ejecución.
Estamos trabajando en un plugin de Babel que se va a utilizar junto con nuestro plugin JSX para que puedas, cuando uses una declaración de props solo de tipo, simplemente vaya a inferir automáticamente la lista de props en tiempo de ejecución e inyectarla en este componente para ti. No necesitas declarar todo dos veces. Una de las implicaciones de esta característica es que esperamos que algunas bibliotecas existentes que están utilizando TSX para crear componentes de vista puedan migrar a esto y luego podamos simplemente enviar solo tipos para todas las props entre tanto la component library como la aplicación. Así que ya no necesitas escribir manualmente una lista de declaraciones en tiempo de ejecución que de alguna manera invierta los tipos de ella, que es una práctica muy común en las bibliotecas de componentes en este momento. Así que eso es una cosa que intentamos resolver. Eventualmente queremos llegar al punto en el que si estás usando typescript, no importa si eres un autor de componentes o un consumidor de componentes, deberías ser capaz de simplemente preocuparte por los tipos y sin preocuparte por la lista de props en tiempo de ejecución. Así que ese es un objetivo a largo plazo que esperamos lograr.
6. Mejoras en Define Emits y Defined Slots
En Vue 3.3, introdujimos define emits más ergonómicos, permitiéndote declarar tipos de eventos usando la sintaxis de tupla etiquetada. Esta característica está inspirada en las macros de Vue, desarrolladas por Kevin, quien ahora es miembro del equipo central. Si estás interesado en explorar ideas experimentales, echa un vistazo a las macros de Vue. Otra mejora es la capacidad de definir slots con tipos, permitiendo una mejor comprobación de tipos y detección de errores en el IDE.
Entonces, otra característica en 3.3 es el define emits más ergonómico. Entonces, si has usado define emits anteriormente, probablemente has encontrado que la firma es un poco extraña. La razón es que esto, de hecho, es el tipo exacto para esta función emit que vas a obtener aquí. Es un poco incómodo de escribir. Así que aquí estamos haciendo algunas pequeñas conversiones de tipo internas para que puedas simplemente decir que tenemos un evento foo, que va a aceptar esto. Entonces, esta sintaxis puede parecer desconocida para algunos. Esto es, de hecho, llamado sintaxis de tupla etiquetada en TypeScript. Entonces, si ignoras esta etiqueta de ID aquí, esto es solo un número normal, una tupla con un solo elemento que es un número. Pero TypeScript también te permite etiquetar tu elemento de tupla. Entonces, puedes darle a cada elemento dentro de una tupla un nombre. Entonces puedes decir que este primer elemento va a ser ID. Y el propósito de eso es que cuando miras el tipo desde otro lugar, te va a dar mejor información. Vas a decir, oh, el primer elemento es el ID, el segundo elemento es eso. Entonces, es como una lista de argumentos, que es el propósito exacto de lo que quieres declarar aquí. Entonces, simplemente convertimos internamente este tipo para darte el tipo de función emit correcto de vuelta. Si estás usando Vue 2, esto de hecho es compatible con las macros de Vue. De hecho, esta característica está inspirada. Simplemente tomamos la característica de las macros de Vue. Y el autor de las macros de Vue, Kevin, ahora es miembro del equipo central. Y ha estado trabajando activamente en muchas ideas experimentales en las macros de Vue. Y si eres de los que les gusta explorar, estás bien con probar cosas nuevas que pueden o no funcionar, deberías echar un vistazo a este proyecto.
Luego están los tipos de slots con defined slots, ¿verdad? Así que una cosa con la que siempre hemos tenido un poco de problema es que los slots no se expresan como parte de las props de los componentes, porque todo sucede en la plantilla. Anteriormente no había forma de expresarlos con tipos, pero ahora te proporcionamos la capacidad de hacerlo. Así que esta macro define slots. La sintaxis aquí requiere que sepas un poco sobre cómo se representan internamente los slots en Vue. Entonces, cuando pasas un slot de un componente padre a un componente hijo, se representan internamente como funciones. Entonces, un slot pasado del padre es de hecho una función que se pasa y va a ser llamada por el hijo. Así que aquí cuando defines slots vas a representarlos como funciones, y una función de slot recibe sus props de slot, que el componente hijo puede pasar al slot del padre. Entonces, cuando declaras slots en un componente de esta manera, el IDE va a detectar esencialmente que estás declarando... si por casualidad haces un error de tipeo, y dices nombre de slot igual a un nombre que no existe aquí, te va a dar un error.
7. Props de Slot en Vue y Define Slots
Las props de slot en Vue 3 proporcionan comprobaciones de tipo para el slot predeterminado. Sin embargo, la comprobación de slots requeridos aún no está implementada. Las macros de Vue se pueden usar con Vue 2.7. Define slots no tiene implicaciones en tiempo de ejecución, solo comprobaciones a nivel de tipo.
Dices oh, este slot, no has declarado este slot, probablemente estás cometiendo un error, y te va a dar comprobaciones de tipo para las props de slot si pasas un mensaje al slot predeterminado y no es una cadena, te lo va a reclamar. Y también en el padre, cuando consumes este componente en el padre, y usas un slot recibes el mensaje del slot de alcance, te va a dar el tipo de cadena correctamente. Así que actualmente una cosa que aún falta es la comprobación de slots requeridos. Como puedes ver, tenemos la capacidad de diferenciar entre un slot requerido versus un slot opcional con esto. Actualmente la comprobación de slot requerido aún no está implementada, pero está planeada y estará allí eventualmente. Y de nuevo, puedes usar esto en Vue 2.7 con las macros de Vue. El soporte de IDE en Volar realmente soporta tanto Vue 2 como Vue 3. Y también, define slots realmente no tiene ningún tipo de implicaciones en tiempo de ejecución, no realiza ninguna comprobación en tiempo de ejecución. Esto es puramente para comprobaciones a nivel de tipo que serán utilizadas por Volar y Vue TSC. También obtienes las mismas comprobaciones cuando simplemente estás ejecutando las comprobaciones de tipo desde la línea de comandos también.
8. Destructuración de Props Reactivas y Define Model
Aquí, estamos introduciendo una característica experimental llamada destructuración de props reactivas. Por defecto, Vue rastrea la reactividad a través del acceso a la propiedad de punto. Sin embargo, cuando estructuras una prop, pierdes la reactividad. Con la característica de destructuración de props reactivas, puedes destruir las props con valores predeterminados mientras mantienes la reactividad. Esta característica añade automáticamente el acceso de punto en tiempo de compilación, proporcionando una sintaxis más limpia para declarar valores predeterminados. Otra característica experimental es define model, que simplifica el proceso de creación de entradas personalizadas con soporte de modelo. En lugar de declarar manualmente las props y los eventos, puedes usar define model para generar una ref que se comporta como una ref normal.
Aquí, estamos entrando en un territorio experimental, así que destructuración de props reactivas. ¿Cuántos de ustedes han oído o probado reactivity transform? ¿Nadie? Entonces, reactivity transform fue una característica experimental que probamos durante bastante tiempo pero finalmente decidimos abandonar. Si no estás familiarizado con reactivity transform, entonces podríamos necesitar proporcionar un poco más de contexto aquí.
Entonces, lo primero es que en Vue, por defecto, toda la magia de reactivity sucede cuando estás usando una propiedad en tu plantilla, usando algo dentro de un observador, Vue automáticamente las rastrea. Y la forma en que Vue las rastrea es rastreando estos accesos a propiedades de punto. Entonces, cuando dices props punto foo, de hecho desencadena un getter o una trampa de proxy internamente, en la que Vue realiza el rastreo mágico. Oh, ok, el tiempo es en realidad... Necesito ir más rápido. Pero la idea es que, por defecto, todo tiene que suceder a través de estos puntos. Por lo que si actualmente estructuras una prop, defines props de esta manera, realmente pierdes la reactivity. Este foo, esta estructura aquí es sólo un custom que nunca va a cambiar. Pero ¿qué tal si podemos hacerlo reactivo y eso es exactamente lo que estamos haciendo aquí.
Entonces, si optas por la característica experimental de destructuración de props reactivas aquí, puedes destruir con valores predeterminados en todo y este foo se mantendrá reactivo, digamos cuando lo uses en una propiedad computada, cuando lo uses dentro de un efecto de observación o lo devuelvas desde un getter, se mantendrá reactivo. Y el truco es realmente simple, simplemente compilamos esto en tiempo de compilación a algo como esto. Entonces, simplemente añadimos automáticamente el acceso de punto por ti para que no necesites escribir tú mismo. Y te da, y la principal razón por la que queremos hacer esto es porque te da una sintaxis mucho más bonita y limpia al declarar valores predeterminados. Si has intentado declarar valores predeterminados con define props antes sabes que haces esto con defaults, lo cual es realmente incómodo, esto es algo que realmente queremos eliminar y esto nos da una forma de hacerlo. Pero de nuevo, esta característica es un poco controvertida en el sentido de que introduce esta nueva magia del compilador que necesitas entender un poco más sobre cómo funciona el rastreo de v-reactivity para entender por qué esto funciona, pero esperamos que las mejoras en DX que proporciona eventualmente valgan la pena. Esto sólo demuestra que si usas esta prop de destructor dentro de un efecto de observación, va a ser rastreada, al igual que props.message. Cada vez que las props del padre cambian, este console.lock se bloqueará de nuevo.
Ahora, define model es otra característica experimental. Si alguna vez has creado un componente, digamos envolviendo una entrada nativa, y quieres tener una entrada personalizada con más características avanzadas, pero aún quieres que el consumidor de tu componente pueda usar el modelo con él. Anteriormente era bastante verboso. Esto es lo que necesitas hacer. Primero necesitas declarar una prop llamada modelValue, luego necesitas tener también un evento correspondiente que va a ser emitido, y luego necesitas hacer tu cableado manual aquí en la entrada nativa, y finalmente juntar todo. Así que con 3.3, esto es lo que necesitas hacer. Simplemente dices define un modelo. Lo que te devuelve es una ref. Esta ref simplemente funciona como una ref normal. Puedes mutarla.
9. Mutando Refs y Uso de Nivel Avanzado
Cuando lo mutas, simplemente emite el evento de vuelta al padre para ti. Y como es una ref, puedes vincularlo a una entrada con el v-model nativo. Y luego está define options. Y hay un poco de nivel avanzado. Si has usado la API de composición y has trabajado con composables, conoces Vue-use. Cuando usas Vue-use, puede aceptar un valor normal o una ref. Pero el problema es que si quieres pasar una propiedad profundamente anidada, se complica. Proporcionamos una nueva función llamada toValue para normalizar todo a un valor. Y está el JsyncPoSource, que tiene posibles implicaciones para TSX.
Cuando lo mutas, simplemente emite el evento de vuelta al padre para ti, y si el valor del padre cambia, simplemente actualizará la ref para ti. Y como es una ref, puedes vincularla a una entrada con el v-model nativo. Entonces puedes trabajar tu lógica adicional encima de esto, lo que hace que sea mucho más sencillo envolver una entrada nativa para construir tus componentes de entrada personalizados encima de ellos.
Y luego está define options. Así que cuando usas script setup si todavía necesitas declarar opciones adicionales, anteriormente necesitabas usar un bloque de script separado. Ahora simplemente usas la macro por lo que no necesitas elegir bloques separados.
Y luego está este pequeño detalle de nivel avanzado. Así que si has usado la API de composición y has trabajado con composables, ¿alguien aquí ha usado Vue-use? Genial, así que cuando usas Vue-use, sabes que Vue-use normalmente puede, cuando quieres pasar algo a una función Vue-use, puede aceptar un valor normal o una ref, por lo que a nivel de tipo podemos pensar en ello como algo llamado maybe ref. Puedes pasar un valor o una ref, pero el problema con eso es, por ejemplo, si tienes un escenario como este, tienes props y dices que quiero pasar props.Vue a ello, pero no puedo simplemente decir use feature props.Vue, porque de esa manera estoy pasando un valor que no va a mantenerse reactivo. Así que lo que teníamos que hacer anteriormente, es que vas a usar dos ref, así que dices dos ref propsVue, estás creando una ref a partir de propsVue y luego la pasas a la función. Y el problema con eso es que dos ref, la firma anterior, no es del todo flexible. La idea aquí es, ¿qué pasa si estás tratando de pasar una ref para una propiedad profundamente anidada? Así que quieres decir tworef props.Vue bar. Ahora esto ya está empezando a parecer un poco raro, y otro inconveniente aquí es que no maneja el caso en el que el foo puede estar o no estar. Así que dices, está bien, puedo refactorizar esto, puedo usar una propiedad computada. Ahora simplemente voy a decir props.vue?bar. Ahora esto manejará lo que sea, no importa si foo está ahí o no. El problema es que a veces podemos usar computed sin pensar demasiado en ello, pero internamente, computing tiene que crear un watcher que mantenga un seguimiento de las cosas e invalide los valores y todo eso. La forma más fácil de hacerlo es si tus composables realmente soportan la aceptación de un getter. Así que proporcionamos una nueva función llamada toValue para que puedas hacer eso. Lo que realmente hace es que dentro de tu composable, vas a decir que foo no es solo un maybe ref o un getter. Y toValue simplemente normaliza todo a un valor, no importa si es un valor o una ref o un getter. Simplemente lo normaliza. Así que puedes hacer esto y no necesitas preocuparte de lo que sea foo. Puede ser cualquier cosa que el usuario quiera pasar y simplemente lo normalizará. Y si piensas en las direcciones de normalización, en el medio tienes maybe, ref, o getter. A la izquierda, podemos usar toRef para normalizar cada uno de ellos en refs. A la derecha, puedes usar toValue para normalizar cada uno de ellos en valores. Así que es una calle de doble sentido.
Bueno, entonces está el JsyncPoSource. Así que quiero mencionar esto principalmente porque esto tiene una posible implicación si estás usando TSX.
10. Soporte TSX y Vue.js 1.0 Beta
Si usas TSX con Vue, opta por esto ahora para evitar cualquier problema cuando se elimine el registro global predeterminado en 3.4. Vue.js 1.0 beta, el generador de sitios estáticos, se lanzará pronto. Se recomienda Vitepress como la mejor herramienta de documentación.
Si no usas TSX, realmente no te concierne, pero si usas TSX con Vue querrás optar por esto ahora para que cuando eliminemos el registro global predeterminado en 3.4 no te afecte de ninguna manera. Entonces sí, ¿y qué sigue? Vue.js 1.0 beta muy pronto ahora que tenemos 3.3 fuera. Este es el generador de sitios estáticos. Si has leído la docs, la Vue.js docs, la Vite docs, RollUp docs de hecho, muchos de estos nuevos proyectos, su documentación se construye en Vitepress y si tienes un proyecto propio, quieres documentar, pruébalo. Personalmente creo que es la mejor herramienta de documentación que existe.
11. Planes Futuros de Vue y Características Emocionantes
Estamos planeando una ronda de limpieza de PR de problemas del núcleo de Vue y priorizando problemas importantes para el próximo sprint menor. En 3.4, nuestro objetivo es estabilizar suspense, mejorar safe teleport y mejorar las invalidaciones de computadora. También tenemos planes emocionantes para el modo Vapor y características adicionales de la plataforma. La propuesta de alcance de la aplicación nativa en el Grupo de Trabajo CSS simplificará la implementación del estilo de alcance de Vue. El contexto asíncrono rastreará la inicialización del componente en pilas de llamadas asíncronas, y las partes del DOM serán un objetivo de compilación crucial para VaporMode. Estos desarrollos harán que VueCorp sea más simple y eficiente.
Lo siguiente es que vamos a hacer una ronda de limpieza de PR de problemas del núcleo de Vue. Tenemos un montón de problemas importantes P4 que queremos abordar antes del próximo sprint menor. Luego, en 3.4, algunas de las cosas que queremos priorizar son estabilizar suspense, algunas mejoras, construir safe teleport y invalidaciones de computadora más eficientes. El objetivo para las futuras versiones menores es que queremos mantenerlas más pequeñas en alcance, para que podamos lanzar más a menudo, lanzar más rápido. En el tercer y cuarto trimestre, vamos a seguir trabajando en el modo Vapor y hay algunas características adicionales de la plataforma a tener en cuenta. Si estás interesado en cómo el futuro de Vue se entrelazará con el nuevo uso de las iniciativas de la plataforma. Una cosa emocionante es la propuesta de alcance de la aplicación nativa que está ocurriendo en el Grupo de Trabajo CSS. En resumen, esta característica nos permitirá implementar completamente la implementación del estilo de alcance de Vue para hacerla mucho más simple y más eficiente, lo cual es una gran cosa. Menos dentro del framework y más simplemente aprovechando las características de la plataforma nativa. Y luego está el contexto asíncrono, que nos permite rastrear el contexto del componente actual en una pila de llamadas asíncronas. Así que en el setup asíncrono, métodos asíncronos y acciones pnet asíncronas, vamos a poder saber qué componente lo inició. Y luego están las partes del DOM, que van a ser un objetivo de compilación importante para VaporMode. Muchas de estas están clasificadas desde más cerca de la materialización hasta las partes del DOM, que es una etapa muy temprana. Pero estas son las cosas que estamos vigilando, que nos emocionan. Creemos que ayudarán a VueCorp a ser más simple y más eficiente.
¡Y eso es todo! Gracias. Muchas gracias a todos. Por favor, pasen a mi oficina. Recuerden, si tienen alguna pregunta, pueden dirigirse a Slido y hacerla. Y mientras esperamos a que la gente saque sus teléfonos y haga algunas preguntas, tengo una pregunta para ustedes. Acabas de anunciar Vue 3.3, y tienes tantas características diferentes, algunas de las características de las que hablaste hoy. ¿Cómo priorizas cuáles quieres trabajar, y qué características te emocionan más?
¿Te refieres dentro del lanzamiento? Sí. Personalmente estoy más emocionado por el soporte de tipo externo, el soporte de tipo importado, principalmente porque ha sido un gran challenge técnico para mí, y durante mucho tiempo, simplemente dudamos si era posible, pero finalmente lo logramos en 3.3. Así que eso es algo bueno para mí, me siento algo aliviado de poder sacar eso por la puerta. Y luego, en general, creo que todas estas características juntas nos dan una bastante buena confianza para decir que los componentes de archivo único de Vue, especialmente con script setup, ahora funcionan muy bien con TypeScript. Vas a tener un muy buen DX cuando estés usando TypeScript con Vue. Así que eso es lo más importante para mí. Genial. Eso es increíble. Así que tenemos algunas preguntas que están llegando.
12. Modo Vapor y Compatibilidad Unref
El Modo Vapor en Vue 3 es una nueva forma de compilar plantillas en un código más eficiente en memoria y rendimiento. Es compatible con el formato de componente existente y ofrece una experiencia de desarrollo más ligera y rápida. Sin embargo, tiene un conjunto limitado de características soportadas. Además, la pregunta sobre cambiar unref para soportar getters no es posible debido al diseño actual de la API y los posibles cambios disruptivos que introduciría.
Algunas preguntas, ¿qué es el modo vapor? Correcto. Lo he mencionado algunas veces en charlas de conferencias pasadas. Así que ahora, la forma en que Vue funciona es que compilamos tus plantillas en JavaScript. Y el JavaScript que producimos ahora todavía se llama funciones de renderizado del DOM virtual. Así que todavía hay algo llamado tiempo de ejecución del DOM virtual. Así que en Vue 2, ordenamos al DOM virtual principalmente porque queríamos proporcionar capacidades de renderizado del servidor. En Vue 3, nos damos cuenta de que el DOM virtual tiene cierta sobrecarga de memoria y tiempo de ejecución cuando se trata de rendimiento, por lo que ya estamos haciendo muchas optimizaciones en tiempo de compilación para hacer el código del DOM virtual generado lo más eficiente posible. Pero aún así, no va a ser tan bueno como si pudiéramos saltarnos el DOM virtual por completo y usar una estrategia de generación de código completamente diferente.
Así que el Modo Vapor es esencialmente esta nueva forma. Va a tomar el mismo formato de componente, el mismo componente de archivo único con el mismo sintaxis de plantilla. No necesita cambiar nada. Inicialmente va a soportar un subconjunto de las características, pero va a ser 100% compatible. Simplemente tomamos el mismo código de plantilla y lo compilamos en algo que va a ser bastante diferente por debajo. Así que algo que va a ser mucho más eficiente en memoria, mucho más rendimiento, y genera un peso más ligero, también requiere menos código en tiempo de ejecución. Así que en general, es algo que va a ser en gran medida transparente a nivel de experiencia de desarrollo por lo que simplemente optas por ello. Cuando optas por ello, obviamente vas a estar limitado a un conjunto de características que soporta, pero va a ser la misma experiencia de vista. Pero el código que genera va a ser mágicamente más ligero, más rápido y más eficiente. Me encanta cuando las cosas simplemente se vuelven mágicamente más ligeras y más eficientes detrás de las escenas.
Así que muchas gracias. Tenemos otra pregunta también, y creo que voy a leer la última línea de esta pregunta primero, que es, se ve impresionante por cierto, pero ¿por qué no cambiar unref para soportar getters de modo que las implementaciones componibles existentes ya lo soporten? Esa es una buena pregunta, de hecho. Así que si lo piensas, ref y unref son los dos contrapartes. Entonces, ¿qué pasa cuando pasas una función a ref? Unref es que realmente creará un ref usando esa función como su valor. Así que unref tiene el mismo problema. Así que si unref recibe una función, ahora lo que hace es, la premisa de la API actual de unref es, digamos, si algo que recibí es un ref, voy a devolver como valor. Si no es un ref, simplemente voy a devolver el valor tal cual. Y una función en realidad cae en la categoría de no ser un ref aquí. Así que si cambiamos unref para simplemente llamar a la función y devolver su valor de retorno, entonces es en realidad un cambio disruptivo. Así que desafortunadamente, pensé en soportar eso en primer lugar. Pero nos dimos cuenta, oh, es un cambio disruptivo. Y no podemos hacer eso.
Vue API: toValue, TSX y Composition API
Introdujimos toValue como una nueva API que funciona de manera similar a unref pero llama a funciones. Al implementar componentes recursivos y dinámicos, TSX es preferido para casos de uso altamente dinámicos. La Composition API se recomienda sobre la Options API para construir bases de código a gran escala y mantenibles, gracias a su mejor integración con TypeScript y su composabilidad.
Entonces necesitamos una nueva API para eso. Es por eso que introdujimos toValue. Entonces, esencialmente, puedes pensar en toValue como unref, pero simplemente llamará a funciones. Sí. Gracias. Gracias. Y gracias también a Canan por hacer esa pregunta.
Tenemos otra pregunta de Mitch. Si estás tratando de implementar componentes recursivos y dinámicos, ¿recomendarías TSX en lugar de usar un SFC? ¿Usando CSS? TSS. Oh, TSX. ¿Componentes recursivos? No creo que haya una diferencia fundamental aquí. Usualmente, cuando la gente recurre a TSX, es porque tienen que lidiar con muchos renderizados de un montón de componentes dinámicos basados en una estructura de data, típicamente. Esto sucede mucho en componentes basados en configuración como un componente de tabla que va a recibir un objeto de opciones para especificar qué campos renderizar en el encabezado, qué filas van a mostrar y todo eso. Todo es altamente dinámico, y realmente vas a tener un tiempo difícil expresando este tipo de lógica usando la sintaxis de la plantilla, pero usando TSX te permite, digamos, construir programáticamente el árbol de componentes basado en estos valores de opción, y ese es el caso más común donde la gente prefiere TSX. Recursivo puede caer en eso, pero si es solo recursivo, realmente no tienes que, pero realmente depende de cuán dinámico sea tu caso de uso. Gracias. Gracias por la pregunta una vez más. Tenemos otra también. Y gente, también pueden votar las preguntas para asegurarse de que hagamos todas las que podamos, tantas como podamos. Tenemos tantas preguntas, y si no llegamos a ninguna, asegúrate de encontrar a Evan arriba. Pero siguiendo, tenemos otra pregunta que está preguntando sobre la composition API. Entonces, ¿dirías que Vue está cambiando a favor de usar la composition API por todas las nuevas características que estás lanzando para dejar de alentar el uso de la options API en algún momento, o la options API siempre tendrá algunos casos donde se alentará sobre la composition API? Entonces, para ser 100% honesto, no creo que haya casos donde yo recomendaría options API sobre composition API. Entonces, la clara ventaja de options API está, diría que está disminuyendo, especialmente cuando se considera TypeScript. Pero en realidad, nuestra productivity a veces no es una métrica completamente objetiva. Puede estar asociada con tu preferencia subjetiva. Cuando estás más contento con la API, eres más productivo. Entonces, si tienes fuertes preferencias personales con los estilos de API, no diría que deberías trabajar en contra de eso. Pero si lo piensas desde una perspectiva puramente pragmática, estás diciendo que quiero construir una base de código a gran scale, mantenible. Entonces recomendaría ir con Composition API, principalmente por la mejor integración de TypeScript y la composabilidad, la capacidad de tomar un componente que has escrito y extraer partes de él, reordenar cosas, y reutilizar cosas a través de componentes. En general, Composition API se presta mucho mejor a estas prácticas en comparación con Options API.
Consejos para trabajar en un equipo de desarrollo
Si personalmente estás bien con procedimientos estrictos o más flexibilidad en un equipo de desarrollo, en última instancia depende de la dinámica del equipo y el acuerdo mutuo. Se necesita algún nivel de convención de código y reglas impuestas para la productividad a largo plazo, pero ser demasiado pedante puede obstaculizar el progreso. Encontrar un equilibrio es clave.
Entonces, es una apuesta a largo plazo mejor. Pero si solo estás haciendo tu cosa personal y dices que la API de opciones todavía se siente bien, y realmente no has encontrado ninguna limitación con ella, entonces por todos los medios puedes seguir con ella. Me encanta cómo incluyes tu felicidad o la felicidad del desarrollador en la producción o en el ciclo de desarrollo como uno de los factores por los que elegirías uno sobre el otro.
Lo que me lleva muy bien al siguiente, que es ¿cuáles son los mejores tips para trabajar juntos en un equipo de desarrollo. ¿Preferirías procedimientos estrictos o más flexibilidad? Es decir, ¿deberían las personas ser flexibles y estar contentas en su propio entorno? ¿O estrictos y vamos a construir el mejor code que podamos? Creo que esto tiene mucho que ver con la dinámica del equipo en primer lugar, ¿verdad? Creo que depende de, cuando tienes un equipo, si tienes un equipo formado por personas con opiniones muy diferentes y también fuertemente arraigadas, entonces no va a ser productivo de ninguna manera, ¿verdad? Así que lo importante es que el equipo necesita estar en la misma página sobre lo que mutuamente acuerdan que es algo que pueden aceptar y trabajar con ello. Personalmente, para mí, creo que realmente va a ser una decisión del equipo. Si yo, digamos, estoy tomando un trabajo y me uno a un equipo, personalmente voy a estar bien con cualquiera dirección. Depende de lo que decidan los líderes del equipo. Creo que algún nivel de convención de code y reglas impuestas es necesario si quieres a largo plazo productivity. Es solo que no quieres ser super pedante al respecto. Haría un ejemplo, ahora mismo, la forma en que formateo mi code es que uso Prettier y atrapo errores con TypeScript. Realmente ya no uso mucho ESLinks. Entonces, si me uno a un proyecto con las reglas de ESLink de Airbnb, voy a decir que no. Esa es la pedantería de la que estoy hablando. Y en tus equipos, en esa scale, ¿dónde dirías que se sientan tus equipos? Probablemente un poco en el extremo más flexible.
Vue y la Magia de la Compilación
La tendencia en todos los marcos es hacia más magia de compilador. Los Componentes de Servidor de React, SvelteKit y Solid Start también dependen en gran medida de la compilación. La realidad es que nos estamos moviendo hacia una escena de marcos más impulsada por el compilador. Angular también está explorando componentes de un solo archivo. No me preocupa que Vue se desvíe del ecosistema de JavaScript porque todos están adoptando marcos impulsados por el compilador.
Genial. Otra pregunta, ¿te preocuparía que Vue esté añadiendo demasiada magia de compilación y se desvíe lentamente del resto del ecosistema de JavaScript? Tienes algo así como el ecosistema de JavaScript y luego todas estas burbujas. ¿Te preocupa en algún momento que Vue se desvíe de eso? No lo creo. De hecho, si observas la tendencia general, la tendencia general en todos los frameworks es que hay cada vez más magia de compilador. Los Componentes de Servidor de React requieren mucha magia de tipo compilador. Sabes, las Acciones de Servidor, que acaban de introducir recientemente, SvelteKit, Svelte es posiblemente aún más mágico en términos de compilación. ¿Verdad? Solid Start también tiene mucha magia de compilación involucrada. Así que, creo que la tendencia general es que las personas están, te guste o no, la realidad es que nos estamos moviendo hacia una escena de framework más impulsada por el compilador. Y en términos de - y si también observas a Angular, hay mucho interés en la comunidad de Angular en este momento de explorar componentes de un solo archivo para Angular. Así que, creo, diría, no, no me preocupa eso, porque todos están haciendo más cosas de compilador hoy en día. Es como lo que dijiste, hacer las cosas en segundo plano para hacerlo más eficiente. Realmente aprecio cuando haces cosas así para nosotros. Realmente lo hago. Y la última, porque sé que casi nos quedamos sin tiempo, es ¿cuál es tu consejo para los equipos que pasan de Vue 2 a Vue 3? Un cambio grande como ese siempre es grande. ¿Tienes algún consejo para la gente? Sí, así que mi consejo honesto es que necesitas hacer una exploración preliminar sobre - como, la situación realmente varía en cómo es tu uso actual de Vue 2. Así que, si tienes un solo proyecto con un bien definido - no te estás desviando demasiado de la forma en que hacemos las cosas por defecto, entonces migrar a Vue 3 es 100% factible. Pero la situación se vuelve - va a variar enormemente en función de las dependencias que uses. ¿Usas alguna - alguna configuración de construcción personalizada loca? Hay un montón de cosas que están fuera del control del núcleo de Vue para poder determinar completamente cuán fácil va a ser para ti migrar a Vue 3. Y tengo que admitir que en algunos casos tal vez no sea la mejor idea actualizar. Así que, creo que lo mínimo que puedes hacer es actualizar a 2.7 y combinarlo con las macros de Vue te dará un porcentaje muy decente de todas las cosas buenas que esperarías de Vue 3. Y si el rendimiento actual y todo lo demás no te está causando dolores de cabeza notables, entonces es una decisión razonable quedarse en Vue 2. Y, si estás preocupado por el cumplimiento del fin de la vida útil, entonces, obviamente, hay Héroes desarrolladores que pueden ayudarte con eso. Así que sí, la triste verdad es, es realmente difícil darte una declaración general y decir, oh, puedes actualizar. Realmente depende de muchos de estos pequeños factores donde tienes que mirar caso por caso base. Así que nuestro esfuerzo se centra en suponer que tienes una sola aplicación utilizando nuestras prácticas recomendadas estándar, entonces te damos este camino que está delineado en la guía de migración. Usas el modo de migración, empiezas a cambiar tus dependencias una por una y eventualmente te deshaces de todas las advertencias de migración y entonces estás en Vue 3. ¡Perfecto! Muchas gracias, aplaudamos a Evan una vez más. Gracias.
Comments