{@attach ...}
Les attachements sont des fonctions qui sont exécutées lorsqu’un élément est monté dans le DOM. Ils peuvent optionnellement renvoyer une fonction qui sera appelée lorsque cet élément sera supprimé du DOM.
Les attachements sont des fonctions qui sont exécutées au sein d’un effet lorsqu’un élément est monté dans le DOM ou lorsqu’un état lu dans la fonction est mis à jour.
De manière optionnelle, ils peuvent renvoyer une fonction qui sera exécutée juste avant que l’attachement soit ré-exécuté, ou juste après que l’élément soit supprimé du DOM.
Les attachements sont disponibles à partir de la version 5.29 de Svelte.
<script>
/** @type {import('svelte/attachments').Attachment} */
function myAttachment(element) {
console.log(element.nodeName); // 'DIV'
return () => {
console.log('nettoyage');
};
}
</script>
<div {@attach myAttachment}>...</div>
<script lang="ts">
import type { Attachment } from 'svelte/attachments';
const myAttachment: Attachment = (element) => {
console.log(element.nodeName); // 'DIV'
return () => {
console.log('nettoyage');
};
};
</script>
<div {@attach myAttachment}>...</div>
Un élément peut avoir autant d’attachements que nécessaire.
Usines à attachements
Un pattern utile est de faire qu’une fonction, comme tooltip
dans cet exemple, renvoie un
attachement
(démo) :
<script>
import tippy from 'tippy.js';
let content = $state('Bonjour !');
/**
* @param {string} content
* @returns {import('svelte/attachments').Attachment}
*/
function tooltip(content) {
return (element) => {
const tooltip = tippy(element, { content });
return tooltip.destroy;
};
}
</script>
<input bind:value={content} />
<button {@attach tooltip(content)}>
Survolez-moi
</button>
<script lang="ts">
import tippy from 'tippy.js';
import type { Attachment } from 'svelte/attachments';
let content = $state('Bonjour !');
function tooltip(content: string): Attachment {
return (element) => {
const tooltip = tippy(element, { content });
return tooltip.destroy;
};
}
</script>
<input bind:value={content} />
<button {@attach tooltip(content)}>
Survolez-moi
</button>
Puisque l’expression tooltip(content)
est exécutée au sein d’un effet, l’attachement
sera détruit et recréé à chaque fois que content
sera mis à jour. La même chose se produit pour
tout état lu à l’intérieur de la fonction de l’attachement lors de sa première exécution. (Si ce
n’est pas ce que vous souhaitez, voir la section Contrôler la ré-exécution des
attachements.)
Attachements inliné
Les attachements peuvent également être inlinés (démo) :
<canvas
width={32}
height={32}
{@attach (canvas) => {
const context = canvas.getContext('2d');
$effect(() => {
context.fillStyle = color;
context.fillRect(0, 0, canvas.width, canvas.height);
});
}}
></canvas>
L’effet imbriqué est exécuté à chaque fois que
color
change, tandis que l’effet extérieur (oùcanvas.getContext(...)
est appelé) n’est exécuté qu’une seule fois, puisqu’il ne lit aucun état réactif.
Passer des attachements aux composants
Lorsqu’utilisé sur un composant, {@attach ...}
va créer une prop dont la clé sera un
Symbol
.
Si le composant étale ensuite ses props sur un élément, ce dernier
recevra ces attachements.
Cela vous permet de créer des composants englobants qui augmentent les éléments (démo) :
<script>
/** @type {import('svelte/elements').HTMLButtonAttributes} */
let { children, ...props } = $props();
</script>
<!-- `props` inclut les attachements -->
<button {...props}>
{@render children?.()}
</button>
<script lang="ts">
import type { HTMLButtonAttributes } from 'svelte/elements';
let { children, ...props }: HTMLButtonAttributes = $props();
</script>
<!-- `props` inclut les attachements -->
<button {...props}>
{@render children?.()}
</button>
<script>
import tippy from 'tippy.js';
import Button from './Button.svelte';
let content = $state('Bonjour !');
/**
* @param {string} content
* @returns {import('svelte/attachments').Attachment}
*/
function tooltip(content) {
return (element) => {
const tooltip = tippy(element, { content });
return tooltip.destroy;
};
}
</script>
<input bind:value={content} />
<Button {@attach tooltip(content)}>
Survolez-moi
</Button>
<script lang="ts">
import tippy from 'tippy.js';
import Button from './Button.svelte';
import type { Attachment } from 'svelte/attachments';
let content = $state('Bonjour !');
function tooltip(content: string): Attachment {
return (element) => {
const tooltip = tippy(element, { content });
return tooltip.destroy;
};
}
</script>
<input bind:value={content} />
<Button {@attach tooltip(content)}>
Survolez-moi
</Button>
Contrôler la ré-exécution des attachements
Les attachements, à la différence des actions, sont pleinement réactifs : {@attach foo(bar)}
sera ré-exécuté lorsque foo
ou bar
(ou tout état lu au sein de
foo
) sont mises à jour :
function function foo(bar: any): (node: any) => void
foo(bar) {
return (node) => {
veryExpensiveSetupWork(node: any
node);
update(node: any
node, bar: any
bar);
};
}
Dans les rares situations où cela pourrait être un problème (par exemple, si foo
coûte cher à
exécuter tout étant indispensable), envisagez de fournir les données via une fonction, et de les
lire dans un effect imbriqué :
function function foo(getBar: any): (node: any) => void
foo(getBar) {
return (node) => {
veryExpensiveSetupWork(node: any
node);
function $effect(fn: () => void | (() => void)): void
namespace $effect
Runs code when a component is mounted to the DOM, and then whenever its dependencies change, i.e. $state
or $derived
values.
The timing of the execution is after the DOM has been updated.
Example:
$effect(() => console.log('The count is now ' + count));
If you return a function from the effect, it will be called right before the effect is run again, or when the component is unmounted.
Does not run during server side rendering.
node: any
node, getBar: any
getBar());
});
}
}Créer des attachements programmatiquement
Pour ajouter des attachements à un objet qui seront ensuite étalés sur un composant ou un élément,
utilisez createAttachmentKey
.
Convertir des actions en attachements
Si vous utilisez une librairies qui fournit uniquement des actions, vous pouvez les convertir en
attachements avec fromAction
, vous permettant ainsi de (par
exemple) les utiliser sur des composants.
Modifier cette page sur Github llms.txt