跳到主要內容

{#snippet ...}

{#snippet name()}...{/snippet}
{#snippet name(param1, param2, paramN)}...{/snippet}

程式碼片段和 render 標籤,是一種在元件內部建立可重複使用標記區塊的方法。您可以不用編寫重複的程式碼,例如 這樣...。

{#each images as image}
	{#if image.href}
		<a href={image.href}>
			<figure>
				<img src={image.src} alt={image.caption} width={image.width} height={image.height} />
				<figcaption>{image.caption}</figcaption>
			</figure>
		</a>
	{:else}
		<figure>
			<img src={image.src} alt={image.caption} width={image.width} height={image.height} />
			<figcaption>{image.caption}</figcaption>
		</figure>
	{/if}
{/each}

...你可以寫成 這樣

{#snippet figure(image)}
	<figure>
		<img src={image.src} alt={image.caption} width={image.width} height={image.height} />
		<figcaption>{image.caption}</figcaption>
	</figure>
{/snippet}

{#each images as image}
	{#if image.href}
		<a href={image.href}>
			{@render figure(image)}
		</a>
	{:else}
		{@render figure(image)}
	{/if}
{/each}

像函式宣告一樣,程式碼片段可以有任意數量的參數,這些參數可以有預設值,並且您可以解構每個參數。但是,您不能使用剩餘參數。

程式碼片段範圍

程式碼片段可以在元件內的任何位置宣告。它們可以參考在自身之外宣告的值,例如在 <script> 標籤中或在 {#each ...} 區塊中(範例)...

<script>
	let { message = `it's great to see you!` } = $props();
</script>

{#snippet hello(name)}
	<p>hello {name}! {message}!</p>
{/snippet}

{@render hello('alice')}
{@render hello('bob')}

...並且它們對相同語彙範圍內的所有事物(即兄弟姐妹,以及這些兄弟姐妹的子節點)「可見」。

<div>
	{#snippet x()}
		{#snippet y()}...{/snippet}

		<!-- this is fine -->
		{@render y()}
	{/snippet}

	<!-- this will error, as `y` is not in scope -->
	{@render y()}
</div>

<!-- this will also error, as `x` is not in scope -->
{@render x()}

程式碼片段可以參考自身和彼此(範例

{#snippet blastoff()}
	<span>🚀</span>
{/snippet}

{#snippet countdown(n)}
	{#if n > 0}
		<span>{n}...</span>
		{@render countdown(n - 1)}
	{:else}
		{@render blastoff()}
	{/if}
{/snippet}

{@render countdown(10)}

將程式碼片段傳遞給元件

在樣板中,程式碼片段就像任何其他值一樣。因此,它們可以作為 props 傳遞給元件(範例

<script>
	import Table from './Table.svelte';

	const fruits = [
		{ name: 'apples', qty: 5, price: 2 },
		{ name: 'bananas', qty: 10, price: 1 },
		{ name: 'cherries', qty: 20, price: 0.5 }
	];
</script>

{#snippet header()}
	<th>fruit</th>
	<th>qty</th>
	<th>price</th>
	<th>total</th>
{/snippet}

{#snippet row(d)}
	<td>{d.name}</td>
	<td>{d.qty}</td>
	<td>{d.price}</td>
	<td>{d.qty * d.price}</td>
{/snippet}

<Table data={fruits} {header} {row} />

把它想像成將內容而不是資料傳遞給元件。這個概念類似於網頁元件中的插槽。

為了方便撰寫,直接元件宣告的程式碼片段會隱式地成為元件的 props(範例

<!-- this is semantically the same as the above -->
<Table data={fruits}>
	{#snippet header()}
		<th>fruit</th>
		<th>qty</th>
		<th>price</th>
		<th>total</th>
	{/snippet}

	{#snippet row(d)}
		<td>{d.name}</td>
		<td>{d.qty}</td>
		<td>{d.price}</td>
		<td>{d.qty * d.price}</td>
	{/snippet}
</Table>

元件標籤內的任何程式碼片段宣告的內容都會隱式地成為 children 程式碼片段的一部分(範例

應用程式
<Button>click me</Button>
按鈕
<script>
	let { children } = $props();
</script>

<!-- result will be <button>click me</button> -->
<button>{@render children()}</button>

請注意,如果您在元件內有內容,則不能有稱為 children 的 prop - 因此,您應避免使用該名稱的 props

您可以宣告程式碼片段 props 為可選。您可以使用可選鏈來在未設定程式碼片段時不渲染任何內容...

<script>
	let { children } = $props();
</script>

{@render children?.()}

...或使用 #if 區塊來渲染回退內容

<script>
	let { children } = $props();
</script>

{#if children}
	{@render children()}
{:else}
	fallback content
{/if}

類型化程式碼片段

程式碼片段實作從 'svelte' 匯入的 Snippet 介面

<script lang="ts">
	import type { Snippet } from 'svelte';

	interface Props {
		data: any[];
		children: Snippet;
		row: Snippet<[any]>;
	}

	let { data, children, row }: Props = $props();
</script>

透過此變更,如果您嘗試使用元件而不提供 data prop 和 row 程式碼片段,就會出現紅色波浪線。請注意,提供給 Snippet 的類型引數是一個元組,因為程式碼片段可以有多個參數。

我們可以透過宣告泛型來進一步加強,讓 datarow 指向相同的類型

<script lang="ts" generics="T">
	import type { Snippet } from 'svelte';

	let {
		data,
		children,
		row
	}: {
		data: T[];
		children: Snippet;
		row: Snippet<[T]>;
	} = $props();
</script>

匯出程式碼片段

.svelte 檔案頂層宣告的程式碼片段可以從 <script module> 匯出,以在其他元件中使用,前提是它們不參考非模組 <script> 中的任何宣告(無論是直接還是間接地,透過其他程式碼片段)(範例

<script module>
	export { add };
</script>

{#snippet add(a, b)}
	{a} + {b} = {a + b}
{/snippet}

這需要 Svelte 5.5.0 或更新版本

程式化程式碼片段

可以使用 createRawSnippet API 以程式化的方式建立程式碼片段。這適用於進階使用案例。

程式碼片段和插槽

在 Svelte 4 中,可以使用 插槽將內容傳遞給元件。程式碼片段功能更強大且更靈活,因此插槽在 Svelte 5 中已棄用。

在 GitHub 上編輯此頁面

上一個 下一個