Перейти к содержимому

{@attach ...}

Привязки (attachments) — это функции, которые выполняются при монтировании элемента в DOM. При необходимости они могут возвращать функцию, которая будет вызвана при удалении элемента из DOM.

App.svelte
<script>
/** @type {import('svelte/attachments').Attachment} */
function myAttachment(element) {
console.log(element.nodeName); // 'DIV'
return () => {
console.log('cleaning up');
};
}
</script>
<div {@attach myAttachment}>...</div>

Элемент может иметь любое количество привязок.

Полезный паттерн — когда функция (например, tooltip в этом примере) возвращает привязку (демонстрация):

App.svelte
<script>
import tippy from 'tippy.js';
let content = $state('Hello!');
/**
* @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)}>
Наведи курсор
</button>

Поскольку выражение tooltip(content) выполняется внутри эффекта, привязка будет уничтожаться и создаваться заново при каждом изменении content.

Привязки также можно создавать встроенным способом (демонстрация):

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

При использовании {@attach ...} на компоненте создаётся проп с ключом-Symbol. Если компонент затем распространяет пропсы на элемент, этот элемент получит привязки.

Это позволяет создавать обёрточные компоненты, расширяющие функциональность элементов (демонстрация):

Button.svelte
<script>
/** @type {import('svelte/elements').HTMLButtonAttributes} */
let { children, ...props } = $props();
</script>
<!-- `props` включает привязки -->
<button {...props}>
{@render children?.()}
</button>
App.svelte
<script>
import tippy from 'tippy.js';
import Button from './Button.svelte';
let content = $state('Hello!');
/**
* @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)}>
Наведи курсор
</Button>

Для добавления привязок к объекту, который будет распространён на компонент или элемент, используйте createAttachmentKey.

Если вы используете библиотеку, которая предоставляет только действия, вы можете преобразовать их в привязки с помощью fromAction, что позволяет, например, использовать их с компонентами.