O que aprendi escrevendo uma biblioteca de componentes no Svelte


Tendo experimentado o Svelte em projetos pessoais, eu queria seguir em frente e adotar uma estrutura maior no projeto. Para fazer isso, escrevi uma biblioteca de componentes átomos esbeltos . Como base, usei o kit de interface do usuário no React, que usamos no trabalho.


Que técnicas Svelte eu aprendi, leia sob o corte.


Este artigo pressupõe que você já esteja familiarizado com os conceitos básicos do Svelte. Caso contrário, recomendo que você leia meus artigos anteriores:
Vida cheia no Svelte
Desenvolvendo um jogo no Svelte 3


A biblioteca está na fase de revisão ativa. Alguns componentes ainda estão faltando, os problemas de acessibilidade não foram resolvidos e nem todos os erros foram corrigidos. Agora estou fazendo um projeto nesta baleia para entender no modo de combate o que precisa ser melhorado primeiro.


Então, o que aprendi escrevendo uma biblioteca de componentes no Svelte.


1. Usando a propriedade de classe


Se você deseja adicionar a propriedade de classe aos parâmetros do seu componente, receberá um erro, porque a palavra é reservada pelo próprio javascript.


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

Você pode resolver esse problema usando a API interna do Svelte. A variável $$ props contém todas as propriedades que são passadas para o componente. No componente pai, você pode passar a propriedade da classe


 <Component class="someClass" /> 

E no próprio componente, defina a classe a partir da variável $$ props .


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

Exemplo no REPL


2. Componentes filho de estilo


Svelte usa isolamento de estilo. Se você adicionou uma classe a um componente, um hash será adicionado a ela e será exclusivo do seu componente e não vazará em nenhum lugar. Mas e se você precisar estilizar um componente filho? É lógico dar-lhe alguma classe e prescrever estilos nos pais. Esse problema é resolvido de maneira simples, usando a diretiva : global ()


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

Exemplo no REPL


Com essa abordagem, você ainda obtém um estilo isolado, mas isso se aplica a toda a hierarquia de componentes filhos


3. Manipuladores de todos os eventos


O componente Svelte deve suportar o evento para que um manipulador externo possa ser atribuído a ele. Prescrever todas as opções para eventos é cansativo. Em vez disso, você pode escrever um manipulador universal que procurará manipuladores de eventos que são passados ​​para o componente e os adicionará ao nosso componente. Vi a ideia com AlexxNB em sua biblioteca de svelte-chota .


Exemplo
 <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} /> 

Exemplo no REPL


Esse método não é totalmente legal, porque usa a API Svelte interna, que pode ser alterada. Espero no futuro o suporte para a diretiva on: * Issue será adicionada no github


4. Detecção de Slot


Se você precisar descobrir se o conteúdo do slot foi transferido, posso oferecer duas opções.


A primeira maneira, legal


Os slots têm um fallback que é exibido se o conteúdo não for transferido. Tendo transformado o apoio dobrável em uma variável, podemos detectar nosso slot.


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

A segunda maneira, semi-legal


Você pode usar a API interna Svelte


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

Exemplo no REPL


5. Portais


O Svelte não aceita portais, como no React, mas é muito simples de fazer. Você pode usar a API do DOM para isso.


 <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 o componente, transferimos para o corpo e, ao remover, removemos nosso portal.
Nota importante: envolva seu portal em uma div, caso contrário, o Svelte poderá remover componentes incorretamente ao desmontar.


6. Animações


O Svelte possui um grande conjunto de animações prontas que podem ser úteis para você em seu trabalho. É muito fácil animar a aparência e o desaparecimento de componentes. Mas animar um bloco pode retardar a exclusão de toda a página. O Svelte aguardará a conclusão da animação antes de remover o componente da árvore. Para evitar isso, use a diretiva local .
Exemplo de tutorial


7. Slots e componentes nomeados


Infelizmente, você não pode transferir um componente para um slot nomeado imediatamente. Problema no github


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

Para transferir um componente para um slot nomeado, envolva-o em uma div ou em qualquer outra tag html.


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

8. Obtendo uma lista de propriedades do componente


Se você precisar obter uma lista de propriedades que são exportadas de um componente, poderá usar a seguinte construção:


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

Eu recebi a ideia de PaulMaly .


9. Encadernação frente e verso


Depois de desenvolver o React, o conceito de ligação bidirecional parece intimidador, mas é apenas à primeira vista. Como resultado, seu aplicativo parecerá mais conciso e permitirá que você se livre de vários manipuladores. Você pode usar uma variável regular e armazenar como armazenamento.


 <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} /> 

Exemplo no REPL


10. Conteúdo editável


Se você precisar tornar o conteúdo de um elemento editável, poderá usar a diretiva contenteditable e vincular os valores a uma variável.


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

Exemplo no REPL


Tamanho do componente


Bem, e onde sem reagir. Mantenha uma comparação do número de linhas de código de componentes no Svelte e no React, que são implementadas aproximadamente da mesma forma. Código e estilos são levados em consideração.



Biblioteca de demonstração
Código fonte
Se você encontrar um bug ou quiser sugerir algo, crie um problema


PS
22 de fevereiro de 2020 será realizado o Svelte Russian Meetup # 1 em Moscou. Detalhes e anúncio oficial no telegrama ao grupo comunitário russo Svelte: @sveltejs


Convido todos a participar!

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


All Articles