{@attach ...}
附件是元素挂载到 DOM 时运行的函数。它们可以选择返回一个函数,该函数稍后在元素从 DOM 中删除时调用。
¥Attachments are functions that run when an element is mounted to the DOM. Optionally, they can return a function that is called when the element is later removed from the DOM.
附件在 Svelte 5.29 及更高版本中可用。
¥[!NOTE] Attachments are available in Svelte 5.29 and newer.
<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>
一个元素可以包含任意数量的附件。
¥An element can have any number of attachments.
附件工厂(Attachment factories)
¥Attachment factories
一个有用的模式是让函数(例如本例中的 tooltip
)返回一个附件 (demo):
¥A useful pattern is for a function, such as tooltip
in this example, to return an attachment (demo):
<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
发生更改时,附件都会被销毁并重新创建。
¥Since the tooltip(content)
expression runs inside an effect, the attachment will be destroyed and recreated whenever content
changes.
内联附件(Inline attachments)
¥Inline attachments
附件也可以内联创建 (demo):
¥Attachments can also be created inline (demo):
<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(...)
的地方)仅运行一次,因为它不读取任何响应式状态。¥[!NOTE] The nested effect runs whenever
color
changes, while the outer effect (wherecanvas.getContext(...)
is called) only runs once, since it doesn’t read any reactive state.
将附件传递给组件(Passing attachments to components)
¥Passing attachments to components
当在组件上使用时,{@attach ...}
将创建一个键为 Symbol
的 prop。如果组件将 spreads 属性添加到元素上,则该元素将接收这些附件。
¥When used on a component, {@attach ...}
will create a prop whose key is a Symbol
. If the component then spreads props onto an element, the element will receive those attachments.
这允许你创建用于扩充元素(demo)的封装器组件:
¥This allows you to create wrapper components that augment elements (demo):
<script>
/** @type {import('svelte/elements').HTMLButtonAttributes} */
let { children, ...props } = $props();
</script>
<!-- `props` includes attachments -->
<button {...props}>
{@render children?.()}
</button>
<script lang="ts">
import type { HTMLButtonAttributes } from 'svelte/elements';
let { children, ...props }: HTMLButtonAttributes = $props();
</script>
<!-- `props` includes attachments -->
<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>
以编程方式创建附件(Creating attachments programmatically)
¥Creating attachments programmatically
要将附件添加到将展开到组件或元素的对象,请使用 createAttachmentKey
。
¥To add attachments to an object that will be spread onto a component or element, use createAttachmentKey
.