特殊元素 #
一、特殊元素概述 #
Svelte 提供了一系列特殊元素,用于在组件中操作 document 的特定部分。
text
┌─────────────────────────────────────────────────────────────┐
│ Svelte 特殊元素 │
├─────────────────────────────────────────────────────────────┤
│ │
│ <svelte:head> 向 <head> 插入内容 │
│ <svelte:body> 向 <body> 添加事件监听 │
│ <svelte:window> 向 window 添加事件监听和绑定 │
│ <svelte:fragment> 用于插槽内容包装 │
│ <svelte:options> 组件选项配置 │
│ <svelte:document> 向 document 添加事件监听 │
│ <svelte:component> 动态组件渲染 │
│ <svelte:element> 动态元素渲染 │
│ <svelte:self> 组件递归渲染 │
│ │
└─────────────────────────────────────────────────────────────┘
二、svelte:head #
2.1 基本用法 #
svelte
<svelte:head>
<title>My Page Title</title>
<meta name="description" content="Page description" />
<link rel="icon" href="/favicon.ico" />
</svelte:head>
<p>Page content</p>
2.2 动态标题 #
svelte
<script>
let pageTitle = 'Home';
</script>
<svelte:head>
<title>{pageTitle} | My App</title>
</svelte:head>
<button onclick={() => pageTitle = 'About'}>Go to About</button>
2.3 SEO 优化 #
svelte
<script>
let { title, description, image } = $props();
</script>
<svelte:head>
<title>{title}</title>
<meta name="description" content={description} />
<meta property="og:title" content={title} />
<meta property="og:description" content={description} />
<meta property="og:image" content={image} />
<meta name="twitter:card" content="summary_large_image" />
</svelte:head>
2.4 加载外部资源 #
svelte
<svelte:head>
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Roboto" />
<script src="https://cdn.example.com/library.js"></script>
</svelte:head>
三、svelte:body #
3.1 基本用法 #
svelte
<script>
function handleMouseMove(event) {
console.log('Mouse position:', event.clientX, event.clientY);
}
</script>
<svelte:body on:mousemove={handleMouseMove} />
3.2 常用事件 #
svelte
<script>
function handleMouseEnter() {
console.log('Mouse entered body');
}
function handleMouseLeave() {
console.log('Mouse left body');
}
function handleClick(event) {
console.log('Body clicked', event.target);
}
</script>
<svelte:body
on:mouseenter={handleMouseEnter}
on:mouseleave={handleMouseLeave}
on:click={handleClick}
/>
3.3 键盘事件 #
svelte
<script>
let lastKey = '';
function handleKeyDown(event) {
lastKey = event.key;
if (event.key === 'Escape') {
console.log('Escape pressed');
}
}
</script>
<svelte:body on:keydown={handleKeyDown} />
<p>Last key: {lastKey}</p>
四、svelte:window #
4.1 事件绑定 #
svelte
<script>
function handleResize() {
console.log('Window resized:', window.innerWidth, window.innerHeight);
}
function handleScroll() {
console.log('Scrolled:', window.scrollY);
}
</script>
<svelte:window
on:resize={handleResize}
on:scroll={handleScroll}
/>
4.2 属性绑定 #
svelte
<script>
let innerWidth = 0;
let innerHeight = 0;
let scrollX = 0;
let scrollY = 0;
</script>
<svelte:window
bind:innerWidth
bind:innerHeight
bind:scrollX
bind:scrollY
/>
<p>Window: {innerWidth}x{innerHeight}</p>
<p>Scroll: ({scrollX}, {scrollY})</p>
4.3 响应式布局 #
svelte
<script>
let innerWidth = 0;
$: isMobile = innerWidth < 768;
$: isTablet = innerWidth >= 768 && innerWidth < 1024;
$: isDesktop = innerWidth >= 1024;
</script>
<svelte:window bind:innerWidth />
{#if isMobile}
<MobileLayout />
{:else if isTablet}
<TabletLayout />
{:else}
<DesktopLayout />
{/if}
4.4 滚动到顶部按钮 #
svelte
<script>
let scrollY = 0;
function scrollToTop() {
window.scrollTo({ top: 0, behavior: 'smooth' });
}
</script>
<svelte:window bind:scrollY />
{#if scrollY > 300}
<button
class="scroll-top"
onclick={scrollToTop}
>
↑ Top
</button>
{/if}
<style>
.scroll-top {
position: fixed;
bottom: 20px;
right: 20px;
padding: 10px 20px;
background: #ff3e00;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
}
</style>
五、svelte:fragment #
5.1 基本用法 #
svelte
<script>
let { } = $props();
</script>
<svelte:fragment slot="content">
<p>Paragraph 1</p>
<p>Paragraph 2</p>
</svelte:fragment>
5.2 多根节点插槽 #
svelte
<script>
import Layout from './Layout.svelte';
</script>
<Layout>
<svelte:fragment slot="header">
<h1>Title</h1>
<nav>Navigation</nav>
</svelte:fragment>
<p>Main content</p>
</Layout>
5.3 条件渲染多元素 #
svelte
<script>
let showExtra = false;
</script>
{#if showExtra}
<svelte:fragment>
<p>Extra paragraph 1</p>
<p>Extra paragraph 2</p>
</svelte:fragment>
{/if}
六、svelte:component #
6.1 动态组件 #
svelte
<script>
import Home from './Home.svelte';
import About from './About.svelte';
import Contact from './Contact.svelte';
const components = { Home, About, Contact };
let currentComponent = 'Home';
let Component = components[currentComponent];
</script>
<nav>
<button onclick={() => Component = Home}>Home</button>
<button onclick={() => Component = About}>About</button>
<button onclick={() => Component = Contact}>Contact</button>
</nav>
<svelte:component this={Component} />
6.2 传递 Props #
svelte
<script>
import Card from './Card.svelte';
import List from './List.svelte';
let currentView = 'card';
let data = { items: [], title: 'My Data' };
</script>
<svelte:component
this={currentView === 'card' ? Card : List}
data={data}
onUpdate={handleUpdate}
/>
6.3 条件组件 #
svelte
<script>
import Loading from './Loading.svelte';
import Error from './Error.svelte';
import Content from './Content.svelte';
let loading = true;
let error = null;
let data = null;
$: Component = loading ? Loading : error ? Error : Content;
$: props = loading ? {} : error ? { error } : { data };
</script>
<svelte:component this={Component} {...props} />
七、svelte:element #
7.1 动态元素 #
svelte
<script>
let tag = 'div';
</script>
<svelte:element this={tag}>
Dynamic element
</svelte:element>
<button onclick={() => tag = 'span'}>Span</button>
<button onclick={() => tag = 'div'}>Div</button>
<button onclick={() => tag = 'section'}>Section</button>
7.2 语义化组件 #
svelte
<script>
let { as = 'div', href } = $props();
</script>
<svelte:element this={href ? 'a' : as} {href}>
<slot />
</svelte:element>
使用:
svelte
<Button>Button</Button>
<Button as="a" href="/link">Link Button</Button>
7.3 标题组件 #
svelte
<script>
let { level = 1 } = $props();
const tag = `h${Math.min(Math.max(level, 1), 6)}`;
</script>
<svelte:element this={tag}>
<slot />
</svelte:element>
使用:
svelte
<Heading level={1}>H1 Title</Heading>
<Heading level={2}>H2 Title</Heading>
<Heading level={3}>H3 Title</Heading>
八、svelte:self #
8.1 递归组件 #
svelte
<script>
let { node } = $props();
</script>
<div class="tree-node">
<span>{node.name}</span>
{#if node.children}
<div class="children">
{#each node.children as child}
<svelte:self node={child} />
{/each}
</div>
{/if}
</div>
8.2 嵌套列表 #
svelte
<script>
let { items, depth = 0 } = $props();
</script>
<ul style="padding-left: {depth * 20}px">
{#each items as item}
<li>
{item.text}
{#if item.children}
<svelte:self items={item.children} depth={depth + 1} />
{/if}
</li>
{/each}
</ul>
8.3 评论组件 #
svelte
<script>
let { comment } = $props();
</script>
<div class="comment">
<div class="header">
<strong>{comment.author}</strong>
<span>{comment.date}</span>
</div>
<p>{comment.text}</p>
{#if comment.replies}
<div class="replies">
{#each comment.replies as reply}
<svelte:self comment={reply} />
{/each}
</div>
{/if}
</div>
九、svelte:options #
9.1 不可变 Props #
svelte
<script>
export let data;
</script>
<svelte:options immutable={true} />
<p>{data.name}</p>
9.2 访问选项 #
svelte
<script>
export let customOption = 'default';
</script>
<svelte:options
immutable={true}
accessors={true}
/>
<p>{customOption}</p>
9.3 命名空间 #
svelte
<svelte:options namespace="svg" />
<circle cx="50" cy="50" r="40" />
十、完整示例 #
10.1 页面布局组件 #
svelte
<script>
import { page } from '$app/stores';
let { title = 'My App', description = '' } = $props();
$: pageTitle = `${title} | My App`;
</script>
<svelte:head>
<title>{pageTitle}</title>
<meta name="description" content={description} />
<link rel="canonical" href={$page.url.href} />
</svelte:head>
<svelte:window bind:scrollY />
<div class="page" class:scrolled={scrollY > 50}>
<header>
<nav>
<a href="/">Home</a>
<a href="/about">About</a>
<a href="/contact">Contact</a>
</nav>
</header>
<main>
<slot />
</main>
<footer>
<p>© 2024 My App</p>
</footer>
</div>
<style>
.page {
min-height: 100vh;
display: flex;
flex-direction: column;
}
header {
position: sticky;
top: 0;
background: white;
transition: box-shadow 0.3s;
}
.scrolled header {
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
}
main {
flex: 1;
padding: 2rem;
}
</style>
10.2 响应式导航 #
svelte
<script>
let innerWidth = 0;
let menuOpen = false;
$: isMobile = innerWidth < 768;
function handleKeyDown(event) {
if (event.key === 'Escape') {
menuOpen = false;
}
}
</script>
<svelte:window bind:innerWidth on:keydown={handleKeyDown} />
<nav>
{#if isMobile}
<button onclick={() => menuOpen = !menuOpen}>
Menu
</button>
{#if menuOpen}
<div class="mobile-menu">
<a href="/">Home</a>
<a href="/about">About</a>
<a href="/contact">Contact</a>
</div>
{/if}
{:else}
<div class="desktop-menu">
<a href="/">Home</a>
<a href="/about">About</a>
<a href="/contact">Contact</a>
</div>
{/if}
</nav>
十一、总结 #
| 元素 | 说明 |
|---|---|
<svelte:head> |
向 <head> 插入内容 |
<svelte:body> |
向 <body> 添加事件 |
<svelte:window> |
绑定 window 属性和事件 |
<svelte:fragment> |
无包装元素的多节点 |
<svelte:component> |
动态组件渲染 |
<svelte:element> |
动态元素渲染 |
<svelte:self> |
组件递归渲染 |
<svelte:options> |
组件选项配置 |
特殊元素要点:
svelte:head用于 SEO 和资源加载svelte:window用于响应式布局svelte:component用于动态组件svelte:element用于动态元素svelte:self用于递归渲染
最后更新:2026-03-28