Les composants Svelte peuvent également être compilés en web components (ou "custom elements") en utilisant l'option customElement: true
. Il est recommandé de spécifier un nom de balise pour le composant en utilisant la balise <svelte:options>
et l'attribut customElement
.
<svelte:options customElement="my-element" />
<!-- en Svelte 3, faire plutôt ceci :
<svelte:options tag="my-element" />
-->
<script>
export let name = 'tout le monde';
</script>
<h1>Bonjour {name} !</h1>
<slot />
Vous pouvez ignorer le nom de balise pour tout composant imbriqué que vous ne voulez pas exposer et les utiliser plutôt comme des composants Svelte normaux. Il sera toujours possible de nommer ce composant au moment de son instanciation si besoin, en utilisant la props statique element
qui contient le constructeur de web component et qui est disponible lorsque l'option de compilateur customElement
est à true
.
ts
importMyElement from './MyElement.svelte';customElements .define ('my-element',MyElement .element );// en Svelte 3, faire plutôt ceci :// customElements.define('my-element', MyElement);
Une fois qu'un web component a été défini, il peut être utilisé comme un élément du DOM classique :
ts
document .body .innerHTML = `<my-element><p>Ceci est du contenu enfant</p></my-element>`;
Par défaut, les web components sont compilés avec l'option accessors: true
, qui indique que n'importe quelle props sera exposée comme propriété de l'élément DOM (et sera traitée comme un attribut modifiable lorsque ce sera possible).
Pour empêcher ce comportement, vous pouvez ajouter l'option accessors={false}
à la balise <svelte:options>
.
ts
constel =document .querySelector ('my-element');// affiche la valeur courante de la propriété 'name'console .log (el .name );// met à jour une nouvelle valeur, mettant à jour le shadow DOMel .name = 'everybody';
Cycle de vie du web componentpermalink
Les web component sont créés à partir de composants Svelte en utilisant une approche de wrapper. Cela signifie que le composant Svelte imbriqué n'a aucune conscience qu'il est au sein d'un web component. Le web component englobant prend lui-même en charge la gestion du cycle de vie.
Quand un web component est créé, le composant Svelte qu'il embarque n'est pas créé immédiatement. Il est uniquement créé lors du tick suivant l'appel à connectedCallback
. Les propriétés assignées au web component avant qu'il ne soit inséré dans le DOM sont temporairement enregistrées et assignées à la création du composant, pour ne pas perdre leur valeur. Toutefois, la même chose ne fonctionne pas pour l'invocation des fonctions exportées par le web component, elles sont uniquement disponibles après le montage du composant. Si vous avez besoin d'invoquer des fonctions avant la création du composant, vous pouvez contourner le problème en utilisant l'option extend
option.
Lorsqu'un web component écrit avec Svelte est créé ou mis à jour, le DOM fantôme reflète la valeur lors du tick suivant, et non immédiatement. Ainsi, les mises à jour peuvent être groupées, et les déplacements DOM qui détachent temporairement (mais de manière synchrone) les éléments du DOM ne déclenchent pas le démontage du composant sous-jacent.
Le composant Svelte sous-jacent est détruit dans le tick suivant l'invocation de disconnectedCallback
.
Options de composantpermalink
Lorsque vous construisez un web component, vous pouvez définir plusieurs aspects en utilisant l'attribut customElement
de <svelte:options>
en tant qu'objet, et ce depuis Svelte 4. Cet objet peut avoir les propriétés suivantes :
tag
: le nom du web component, obligatoireshadow
: champ optionnel dont la valeur peut être"none"
pour ignorer la création du noeud fantôme racine. Notez que les styles ne seront alors plus encapsulés, et que ne pourrez plus utiliser de slotprops
: an optional property to modify certain details and behaviors of your component's properties. It offers the following settings:attribute: string
: Pour mettre à jour une props d'un web component, vous avez deux alternatives : soit affecter la props sur la référence de l'élément comme illustré juste au-dessus ou utiliser un attribut HTML. Pour cette dernière, le nom par défaut de l'attribut est le nom de la props en minuscules. Vous pouvez modifier ceci avecattribute: "<nom que vous voulez>"
reflect: boolean
: Par défaut, les props mises à jour ne sont pas reflétées dans le DOM. Pour activer ce comportement, utiliserreflect: true
.type: 'String' | 'Boolean' | 'Number' | 'Array' | 'Object'
: Si vous convertissez une valeur d'attribut en valeur de props pour la refléter dans le DOM, la valeur de la props est supposée de typeString
par défaut. Ce n'est pas toujours correct. Par exemple, pour un nombre, vous pouvez utilisertype: "Number"
extend
: une propriété optionnelle qui attend une fonction comme argument. Cette fonction est passée à la classe du web component générée par Svelte et attend que vous retourniez une classe de web component. Cela est utile si vous ave des contraintes particulières concernant le cycle de vie du web component ou si vous voulez améliorer la classe pour utiliser par exemple les ElementInternals (en anglais) pour une meilleure intégration des formulaires.
<svelte:options
customElement={{
tag: 'custom-element',
shadow: 'none',
props: {
name: { reflect: true, type: 'Number', attribute: 'element-index' }
},
extend: (customElementConstructor) => {
// Étend la classe pour lui permettre de participer aux formulaires HTML
return class extends customElementConstructor {
static formAssociated = true;
constructor() {
super();
this.attachedInternals = this.attachInternals();
}
// Ajoutez la fonction ici, pas en-dessous dans le composant
// pour qu'elle soit toujours accessible, pas seulement lorsque
// le composant Svelte sous-jacent est monté
randomIndex() {
this.elementIndex = Math.random();
}
};
}
}}
/>
<script>
export let elementIndex;
export let attachedInternals;
// ...
function check() {
attachedInternals.checkValidity();
}
</script>
...
Limitationspermalink
Les web components sont un bon moyen de packager des composants pour une utilisation dans une application développée dans une autre technologie que Svelte, puisqu'ils fonctionneront avec du HTML et JavaScript natifs mais aussi avec la plupart des frameworks. Il y a cependant des différences importantes à connaître :
- Le style est encapsulé, plutôt que simplement scopé. Cela signifie que tout style défini en dehors du composant (par exemple, celui défini dans un fichier
global.css
et celui défini avec:global(...)
) ne s'appliquera pas au web component - Plutôt que d'être extrait dans un fichier
.css
séparé, le style est inliné directement en tant questring
JavaScript - Les web components ne sont généralement pas faits pour être rendus côté serveur, puisque le DOM fantôme est invisible tant que le code JavaScript n'est pas chargé
- En Svelte, les éléments slottés sont rendus de manière lazy. Dans le DOM, le rendu est "impatient". En d'autres termes, le composant sera toujours créé même si l'élément
<slot>
est à l'intérieur d'un bloc{#if ...}
. De la même manière, inclure un<slot>
dans un bloc{#each ...}
ne rendra pas l'enfant plusieurs fois - La directive
let:
n'a aucun effet, car les web components n'ont aucun moyen de passer de la donnée au composant parent qui fournit le slot - Des polyfills sont nécessaires pour supporter de vieux navigateurs
- Vous pouvez utiliser la fonctionnalité Svelte de contexte entre des composants Svelte classiques à l'intérieur d'un web component, mais vous ne pouvez pas l'utiliser entre différents web component. En d'autres mots, vous ne pouvez pas utiliser
setContext
dans un web component parent et lire ce contexte avecgetContext
dans un web component enfant.
Lorsqu'un web component écrit avec Svelte est créé ou mis à jour, le DOM fantôme reflète la valeur dans le rendu suivant, et non immédiatement. Ainsi, les mises à jour peuvent être groupées, et les déplacements DOM qui détachent temporairement (mais de manière synchrone) les éléments du DOM ne déclenchent pas le démontage du composant sous-jacent.