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

Attachements inliné

Les attachements peuvent également être inliné (démo) :

App
<script>
	import { paint } from './gradient.js';
</script>

<canvas
	width={32}
	height={32}
	{@attach (canvas) => {
		const context = canvas.getContext('2d');

		$effect(() => {
			let frame = requestAnimationFrame(function loop(t) {
				frame = requestAnimationFrame(loop);
				paint(context, t);
			});

			return () => {
				cancelAnimationFrame(frame);
			};
		});
	}}
></canvas>
<script lang="ts">
	import { paint } from './gradient.js';
</script>

<canvas
	width={32}
	height={32}
	{@attach (canvas) => {
		const context = canvas.getContext('2d');

		$effect(() => {
			let frame = requestAnimationFrame(function loop(t) {
				frame = requestAnimationFrame(loop);
				paint(context, t);
			});

			return () => {
				cancelAnimationFrame(frame);
			};
		});
	}}
></canvas>

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>

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.

Modifier cette page sur Github llms.txt

précédent suivant