Svelte 一些特殊的 elements
tags: Svelte
category: Front-End
description: Svelte 一些特殊的 elements
created_at: 2023/04/18 22:00:00
前言
雖然上一篇在 Context
不小心偷偷帶到了其中一個特殊的元素(svelte:self
),不過沒關係,這邊一次把他補齊。
有以下的特殊元素:
<svelte:self>
<svelte:component>
<svelte:element>
<svelte:window>
<svelte:document>
<svelte:body>
<svelte:head>
<svelte:options>
<svelte:fragment>
<svelte:self>
上一篇有提到,這就是可以遞迴(recursive
)自己組件的元素。
這個組件因為是遞迴自己本身,所以不能放在頂層(這樣就沒有結束條件了)。
貼個官方範例:
<script>
export let count;
</script>
{#if count > 0}
<p>counting down... {count}</p>
<svelte:self count="{count - 1}"/>
{:else}
<p>lift-off!</p>
{/if}
<svelte:component>
這個類似於 Vue
當中的 <component :is="" />
,是個方便偷懶的東西。
總之就是可以動態的去呈現組件,像是下面這樣:
<script lang="ts">
import A from '../components/A.svelte';
import B from '../components/B.svelte';
import C from '../components/C.svelte';
const components = [A, B, C];
let selectedComponent = components[0];
</script>
<h1>App</h1>
<select bind:value={selectedComponent}>
{#if selectedComponent.name === undefined}
<option disabled selected value="">Please select item</option>
{:else}
{#each components as component (component.name)}
<option value={component}>{component.name?.match(/Proxy<(.*)>/)?.[1]}</option>
{/each}
{/if}
</select>
<hr />
<svelte:component this={selectedComponent} />
那個 {component.name?.match(/Proxy<(.*)>/)?.[1]}
不是很重要,我只是為了讓他呈現出來的文字好看一些而已。
另外他也可以傳遞 props
下去,可以自己嘗試。
<svelte:element>
這個和前一個 <svelte:component>
很像,只是 component
是針對自訂的組件(也就是大小開頭的元素),而 element
只針對內建的元素。
<script lang="ts">
const elements = ['h1', 'h2', 'h3'];
let selectedElement = elements[0];
</script>
<h1>App</h1>
<select bind:value={selectedElement}>
{#each elements as element (element)}
<option value={element}>{element}</option>
{/each}
</select>
<hr />
<svelte:element this={selectedElement}>{selectedElement}</svelte:element>
另外要注意的是,如果你動態指定元素的時候不能夠 bind:value
,也就是下面這樣是不行的:
<script>
let text = '';
</script>
<svelte:element this={'input'} bind:value={text} />
{text}
但是下面這樣可以,因為他不是動態指定:
<svelte:element this="input" bind:value={text} />
啊可是你這樣不如:
<input type="text" bind:value={text} />
然後也不能在動態帶入 void
元素的時候有內容。
如果你帶入 void
元素且有子元素,且
- 靜態帶入: 會把子元素呈現在兄弟節點(
sibling node
)上,也就是呈現在之後。 - 動態帶入: 會把子元素包進去但顯示不出來,且會出現一段提示訊息,例如:
<svelte:element this="hr"> is self-closing and cannot have content.
<svelte:window>
基本上就是在一開始的時候 window
還不存在,如果你想對 window
做事就可以依靠這個元素,可以在上面綁事件,或是得到一些資訊:
innerWidth
innerHeight
outerWidth
outerHeight
scrollX
scrollY
online
: 的別名window.navigator.onLine
然而上面只有 scrollX
、scrollY
可以操作,其他都是唯讀的(單純取值)。
下面用一個簡單的範例,雖然沒做什麼特別的事。
<script lang="ts">
let y: number;
let height: number;
</script>
<svelte:window
bind:scrollY={y}
bind:innerHeight={height}
on:click={() => console.log('click window')}
/>
<div>y: {y}</div>
<div>height: {height}</div>
另外也要注意,svelte:window
這個元素只能出現在頂層,雖然我想應該也沒人會把他用其他東西包起來吧
<svelte:document>
跟 svelte:window
很像,只是操作對象變成 document
,一樣只能放在頂層。
然後官方有提醒到說不要在上面綁 mouseenter
、mouseleave
之類的,因為可能不會在所有瀏覽器中運作,如果要使用請看下一個 <svelte:body>
<svelte:body>
老樣子,只是操作對象變成 body
。
<svelte:head>
雖然很想直接說跟上面都很像,不過因為 head
應該是比較常會出現的東西(?),在你要改 head
的時候非常方便,例如 title
、meta
之類的,像 React
還要裝套件來做這件事,Svelte
直接幫你搞定。
<svelte:options>
這個是修改一些編譯器的設定(以組件為範圍),因為選項有很多,所以先偷懶一下
<svelte:fragment>
終於到了最後一個,這個很單純,就類似 Vue
當中的 <template>
,或者是 React
當中的 <React.Fragment>
或 <></>
,總之就是可以包住一堆元素,然後不會把自己呈現出來(只呈現包住的東西)的元素。
但是這邊比較特別的是他只允許被放在子組件下面,也就是幫忙 <slot>
這個標籤。
例如:
Box.svelte
<div>
<slot />
</div>
然後可以這樣使用:
<script lang="ts">
import Box from '../components/Box.svelte';
</script>
<Box>
<svelte:fragment>
<div>1</div>
<div>2</div>
<div>3</div>
</svelte:fragment>
</Box>
他就不會多呈現一層東西在外層,雖然如果你是要不影響排版,也可以純粹透過 CSS
做到這件事,不見得要透過這個特殊元素,如果你比賽忘記還有救。
然後他也是可以指定要補哪個 slot
的:
<svelte:fragment slot="header">
<div>Header</div>
</svelte:fragment>
總結
這次一篇把 Svelte
提供的特殊元素介紹了一遍,除了中間偷懶了一個。
常用的應該就那些,反正忘了再去翻一下就好,至少知道有提供這些功能。