{@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) => void
foo(bar) {
return (node) => {
veryExpensiveSetupWork(node: any
node);
update(node: any
node, bar: any
bar);
};
}
まれにこれが問題になるとき(例えば foo
が高コストかつ避けられないセットアップ作業をするときなど)には、データを関数内で渡し、子 effect で読み取ることを検討してください:
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());
});
}
}プログラムによる attachment の作成
コンポーネントや要素に展開されるオブジェクトに attachment を追加するには、 createAttachmentKey
を使います。
action から attachment への変換
action のみを提供するライブラリを使用している場合、 fromAction
で action を attachment に変換できます。これにより、(例えば)コンポーネントで使えるようになります。
Edit this page on GitHub llms.txt