Skip to main content

{@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.

App
<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) :

App
<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) :

App
<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) :

Button
<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>
App
<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) => voidfoo(bar) {
	return (node) => {
		veryExpensiveSetupWork(node: anynode);
		update(node: anynode, bar: anybar);
	};
}

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) => voidfoo(getBar) {
	return (node) => {
		veryExpensiveSetupWork(node: anynode);

		
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.

https://svelte.dev/docs/svelte/$effect

@paramfn The function to execute
$effect
(() => {
update(node: anynode, getBar: anygetBar()); }); } }

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

précédent suivant