{@attach ...}
Attachment は要素がDOMにマウントされたとき、または関数内で読み取られる state が更新されたときに、 effect 内で実行される関数です。
オプションとして、 attachment が再実行される前、または要素がDOMから削除された後に呼び出される関数を返すこともできます。
attachment は Svelte 5.29 以降で利用できます。
<script>
/** @type {import('svelte/attachments').Attachment} */
function myAttachment(element) {
console.log(element.nodeName); // 'DIV'
return () => {
console.log('cleaning up');
};
}
</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('cleaning up');
};
};
</script>
<div {@attach myAttachment}>...</div>ひとつの要素はいくつでも attachment を持つことができます。
Attachmentファクトリ
便利なパターンとして、例にある tooltip のような関数が attachment を返す方法があります(デモ):
<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)}>
Hover me
</button><script lang="ts">
import tippy from 'tippy.js';
import type { Attachment } from 'svelte/attachments';
let content = $state('Hello!');
function tooltip(content: string): Attachment {
return (element) => {
const tooltip = tippy(element, { content });
return tooltip.destroy;
};
}
</script>
<input bind:value={content} />
<button {@attach tooltip(content)}>
Hover me
</button>tooltip(content) 式は effect 内で実行されるため、 content が変更されるたびに attachment は破棄され再作成されます。attachment 関数の 内部 で読み取られた state についても、最初に実行されたときに同じことが起こります。 (これが望ましくないときは、 Attachment の再実行タイミングを制御する を参照してください。)
インライン attachment
Attachments はインラインで作成することもできます (デモ):
<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>ネストされた effect は
colorが変更されるたびに実行されますが、外部の effect (canvas.getContext(...)が呼び出される箇所) はリアクティブな state を読み取らないため、一度しか実行されません。
コンポーネントへの attachment の受け渡し
コンポーネントで {@attach ...} を使うと、キーが Symbol の props を作成します。コンポーネントが props を要素に 展開(spreads) すると、その要素は展開された attachment を受け取ります。
これにより、要素を拡張する ラッパーコンポーネント を作成できます (デモ):
<script>
/** @type {import('svelte/elements').HTMLButtonAttributes} */
let { children, ...props } = $props();
</script>
<!-- `props` には attachment が含まれます -->
<button {...props}>
{@render children?.()}
</button><script lang="ts">
import type { HTMLButtonAttributes } from 'svelte/elements';
let { children, ...props }: HTMLButtonAttributes = $props();
</script>
<!-- `props` には attachment が含まれます -->
<button {...props}>
{@render children?.()}
</button><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)}>
Hover me
</Button><script lang="ts">
import tippy from 'tippy.js';
import Button from './Button.svelte';
import type { Attachment } from 'svelte/attachments';
let content = $state('Hello!');
function tooltip(content: string): Attachment {
return (element) => {
const tooltip = tippy(element, { content });
return tooltip.destroy;
};
}
</script>
<input bind:value={content} />
<Button {@attach tooltip(content)}>
Hover me
</Button>Attachment の再実行タイミングを制御する
attachment は actions と異なり、完全にリアクティブです。 {@attach foo(bar)} は foo または bar (あるいは foo の内部で読み取られた state) の変更で再実行されます:
function function foo(bar: any): (node: any) => voidfoo(bar) {
return (node) => {
veryExpensiveSetupWork(node: anynode);
update(node: anynode, bar: anybar);
};
}まれにこれが問題になるとき(例えば foo が高コストかつ避けられないセットアップ作業をするときなど)には、データを関数内で渡し、子 effect で読み取ることを検討してください:
function function foo(getBar: any): (node: any) => voidfoo(getBar) {
return (node) => {
veryExpensiveSetupWork(node: anynode);
function $effect(fn: () => void | (() => void)): void
namespace $effectRuns 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: anynode, getBar: anygetBar());
});
}
}プログラムによる attachment の作成
コンポーネントや要素に展開されるオブジェクトに attachment を追加するには、 createAttachmentKey を使います。
action から attachment への変換
action のみを提供するライブラリを使用している場合、 fromAction で action を attachment に変換できます。これにより、(例えば)コンポーネントで使えるようになります。
Edit this page on GitHub llms.txt