Lo que aprendí escribiendo una biblioteca de componentes en Svelte


Después de haber probado Svelte en proyectos personales, quería seguir adelante y llevar un marco más amplio al proyecto. Para esto, escribió una biblioteca de componentes de átomos esbeltos . Como base, tomé el kit de interfaz de usuario en React, que usamos en el trabajo.


Qué técnicas aprendí Svelte, leí debajo del corte.


Este artículo asume que ya está familiarizado con los conceptos básicos de Svelte. Si no, te recomiendo que primero leas mis artículos anteriores:
Vida plena en Svelte
Desarrollando un juego en Svelte 3


La biblioteca está en la fase de revisión activa. Todavía faltan algunos componentes, no se han resuelto los problemas de accesibilidad y no se han solucionado todos los errores. Ahora estoy haciendo un proyecto sobre esta ballena para entender en modo de combate lo que debe mejorarse primero.


Entonces, lo que aprendí escribiendo una biblioteca de componentes en Svelte.


1. Usando la propiedad de clase


Si desea agregar la propiedad de clase a los parámetros de su componente, obtendrá un error, porque la palabra está reservada por el propio JavaScript.


<script> export let class = ''; // !!!  !!! </script> 

Puede resolver este problema utilizando la API interna de Svelte. La variable $$ props contiene todas las propiedades que se pasan al componente. En el componente principal, puede pasar la propiedad de clase


 <Component class="someClass" /> 

Y en el componente en sí, establezca la clase desde la variable $$ props .


 <div class={$$props.class} /> 

Ejemplo en REPL


2. Diseño de componentes secundarios


Svelte usa aislamiento de estilo. Si agregó una clase en un componente, se agregará un hash y será exclusivo de su componente y no se filtrará en ninguna parte. Pero, ¿qué pasa si necesita diseñar un componente hijo? Es lógico darle un poco de clase y prescribir estilos en los padres. Este problema se resuelve de manera bastante simple, usando la directiva : global ()


 <script> import Component from "./Component.svelte"; </script> <div class="parent"> <Component class="childClass" /> </div> <style> .parent :global(.childClass) { color: red; } </style> 

Ejemplo en REPL


Con este enfoque, aún obtiene un estilo aislado, pero eso se aplica a toda la jerarquía de componentes secundarios


3. Manejadores de todos los eventos.


El componente Svelte debe admitir el evento para que se le pueda asignar un controlador externo. Prescribir todas las opciones para eventos es agotador. En su lugar, puede escribir un controlador universal que buscará controladores de eventos que se pasen al componente y los agregará a nuestro componente. Encontré la idea con AlexxNB en su biblioteca esbelta-chota .


Ejemplo
 <script> import { current_component, bubble, listen } from "svelte/internal"; function getEventsAction(component) { return node => { const events = Object.keys(component.$$.callbacks); const listeners = []; events.forEach(event => listeners.push(listen(node, event, e => bubble(component, e))) ); return { destroy: () => { listeners.forEach(listener => listener()); } }; }; } const events = getEventsAction(current_component); export let value; </script> <input use:events {value} /> 

Ejemplo en REPL


Este método no es completamente legal, porque utiliza la API interna de Svelte, que puede cambiar. Espero en el futuro soporte para on: * La directiva de problemas se agregará en github


4. Detección de ranuras


Si necesita averiguar si se transfieren los contenidos de la ranura, entonces puedo ofrecerle dos opciones.


La primera forma, legal


Las ranuras tienen un respaldo que se muestra si el contenido no se transfiere. Habiendo convertido el respaldo plegable en una variable, podemos detectar nuestra ranura.


 <script> let footerRef = null; $: isFooterExists = Boolean(footerRef); </script> <slot name="footer"> <div bind:this={footerRef} /> </slot> {isFooterExists ? ' ' : ' '} 

La segunda forma, semi legal


Puedes usar la API interna de Svelte


 const isFooterExists = Boolean($$props.$$slots && $$props.$$slots.footer); 

Ejemplo en REPL


5. Portales


Svelte no acepta portales, como en React, pero es muy simple de hacer. Puede usar la API del DOM para esto.


 <script> import { onMount } from "svelte"; let ref; onMount(() => { document.body.appendChild(ref); return () => { document.body.removeChild(ref); }; }); </script> <div> <div bind:this={ref}>content</div> </div> 

Para montar el componente, lo transferimos al cuerpo y, al eliminarlo, eliminamos nuestro portal.
Nota importante: envuelva su portal en un div, de lo contrario, Svelte puede eliminar componentes incorrectamente al desmontar.


6. Animaciones


Svelte tiene un gran conjunto de animaciones listas para usar que pueden serle útiles en su trabajo. Es muy fácil animar la aparición y desaparición de componentes. Pero animar un bloque puede ralentizar la eliminación de toda la página. Svelte esperará a que se complete la animación antes de eliminar el componente del árbol. Para evitar esto, use la directiva local .
Ejemplo tutorial


7. Ranuras y componentes con nombre


Desafortunadamente, no puede transferir un componente a una ranura con nombre de inmediato. Problema en github


 <Component> <Child slot='footer'/> </Component> <!--    --> 

Para transferir un componente a una ranura con nombre, envuélvalo en un div o cualquier otra etiqueta html.


 <Component> <div slot='footer'> <Child /> </div> </Component> <!-- ! --> 

8. Obtener una lista de propiedades de componentes


Si necesita obtener una lista de propiedades que se exportan desde un componente, puede usar la siguiente construcción:


 <script> import Component from './Component.svelte'; const [_, ...props] = Object.getOwnPropertyNames(Component.prototype); </script> {JSON.stringify(props)} 

Tengo la idea de PaulMaly .


9. Encuadernación a doble cara


Después de desarrollar en React, el concepto de enlace bidireccional parece intimidante, pero es solo a primera vista. Como resultado, su aplicación se verá más concisa y le permitirá deshacerse de un montón de controladores. Puede usar tanto una variable regular como almacenar como almacenamiento.


 <script> import Input from "./Input.svelte"; import { writable } from "svelte/store"; let letValue = "test let"; const storeValue = writable("test store"); </script> <Input bind:value={letValue} /> <Input bind:value={$storeValue} /> 

Ejemplo en REPL


10. Contenido editable


Si necesita hacer que el contenido de un elemento sea editable, puede usar la directiva contenteditable y vincular los valores en una variable.


 <script> let value = "Edit me"; </script> <div contenteditable="true" bind:textContent={value}>{value}</div> <div>Value: {value}</div> 

Ejemplo en REPL


Tamaño del componente


Bueno, y donde sin reaccionar. Mantenga una comparación del número de líneas de código de componentes en Svelte y React, que se implementan aproximadamente igual. El código y los estilos se tienen en cuenta.



Biblioteca de demostración
Código fuente
Si encuentra un error o desea sugerir algo, cree un problema


PS
El 22 de febrero de 2020 se realizará el Svelte Russian Meetup # 1 en Moscú. Detalles y el anuncio oficial en el telegrama al grupo de la comunidad rusa Svelte: @sveltejs


¡Invito a todos a participar!

Source: https://habr.com/ru/post/473598/


All Articles