首页 / Svelte 5 入门教程 / <svelte:window>/<svelte:document>/<svelte:body>

Svelte 5 入门教程

<svelte:window>/<svelte:document>/<svelte:body>

本教程共 50 篇 · 第 30 篇 · 更新于 2026-08-05 · 约 6 分钟阅读

SvelteSvelte 5svelte:windowsvelte:documentsvelte:body特殊元素

本节目标:学会用 svelte:window、svelte:document、svelte:body 三个特殊元素监听全局事件和绑定窗口属性。

三个特殊元素干什么用

有时候你需要监听 windowdocumentdocument.body 上的事件。如果直接用 window.addEventListener,你还得记得在组件卸载时移除监听器,还要处理 SSR 时 window 不存在的问题。

这三个特殊元素帮你处理了所有麻烦事:

元素绑定目标主要用途
<svelte:window>window窗口事件、滚动位置、窗口尺寸
<svelte:document>documentvisibilitychange 等文档事件
<svelte:body>document.bodymouseenter/mouseleave 等事件
Note

这三个元素只能出现在组件的顶层,不能放在 {#if} 或其他元素内部。

svelte:window 事件监听

最基础的用法:监听窗口事件。

<script>
	function handleKeydown(event) {
		console.log(`按下了 ${event.key} 键`);
	}
</script>

<svelte:window onkeydown={handleKeydown} />

组件卸载时,Svelte 自动移除监听器,你不用写任何清理代码。SSR 时也不会报错。

svelte:window 属性绑定

<svelte:window> 支持绑定以下属性:

属性类型说明
innerWidth只读窗口内部宽度
innerHeight只读窗口内部高度
outerWidth只读窗口外部宽度
outerHeight只读窗口外部高度
scrollX可写水平滚动位置
scrollY可写垂直滚动位置
online只读网络在线状态
devicePixelRatio只读设备像素比

滚动位置绑定

<script>
	let scrollY = $state(0);
</script>

<!-- 绑定垂直滚动位置 -->
<svelte:window bind:scrollY />

<p>当前滚动位置:{Math.round(scrollY)}px</p>

<div style="height: 2000px;">
	往下滚动试试
</div>
Note

初始渲染时页面不会自动滚动到绑定值的位置,这是为了避免可访问性问题。只有后续的变量变化才会触发滚动。如果你需要在组件挂载时滚动,在 $effect 里调用 scrollTo()

窗口尺寸绑定

<script>
	let innerWidth = $state(0);
	let innerHeight = $state(0);
</script>

<svelte:window bind:innerWidth bind:innerHeight />

<p>窗口尺寸:{innerWidth} x {innerHeight}</p>

网络状态绑定

<script>
	let online = $state(true);
</script>

<svelte:window bind:online />

<p>
	{#if online}
		网络已连接
	{:else}
		网络已断开
	{/if}
</p>

svelte:document

<svelte:document> 用于监听 document 上的事件。有些事件(比如 visibilitychange)不会在 window 上触发,必须在 document 上监听。

<script>
	function handleVisibilityChange() {
		if (document.hidden) {
			console.log('用户切换到了其他标签页');
		} else {
			console.log('用户回来了');
		}
	}
</script>

<svelte:document onvisibilitychange={handleVisibilityChange} />

<svelte:document> 也支持属性绑定:

属性说明
activeElement当前获得焦点的元素
fullscreenElement全屏元素
pointerLockElement指针锁定元素
visibilityState页面可见性状态
<script>
	let visibilityState = $state('');
</script>

<svelte:document bind:visibilityState />

<p>页面状态:{visibilityState}</p>

svelte:body

<svelte:body> 用于监听 document.body 上的事件。有些事件(比如 mouseentermouseleave)不在 window 上触发,但在 body 上触发。

<script>
	let isHovering = $state(false);

	function handleMouseenter() {
		isHovering = true;
	}

	function handleMouseleave() {
		isHovering = false;
	}
</script>

<svelte:body
	onmouseenter={handleMouseenter}
	onmouseleave={handleMouseleave}
/>

{#if isHovering}
	<p>鼠标在页面上</p>
{:else}
	<p>鼠标离开了页面</p>
{/if}

实战:滚动返回顶部按钮

一个常见的实战场景:滚动超过一定距离后显示”返回顶部”按钮。

<script>
	let scrollY = $state(0);

	function scrollToTop() {
		window.scrollTo({ top: 0, behavior: 'smooth' });
	}
</script>

<svelte:window bind:scrollY />

<div style="height: 3000px; padding: 20px;">
	往下滚动...
</div>

<!-- 滚动超过 200px 时显示按钮 -->
{#if scrollY > 200}
	<button
		onclick={scrollToTop}
		style="position: fixed; bottom: 20px; right: 20px; padding: 10px 20px; background: #6c5ce7; color: white; border: none; border-radius: 4px; cursor: pointer;"
	>
		返回顶部
	</button>
{/if}

实战:响应式布局

根据窗口宽度切换不同的布局类名。

<script>
	let innerWidth = $state(0);

	let layout = $derived(
		innerWidth < 768 ? 'mobile' :
		innerWidth < 1024 ? 'tablet' :
		'desktop'
	);
</script>

<svelte:window bind:innerWidth />

<div class="container" data-layout={layout}>
	<p>当前布局:{layout}</p>
	<p>窗口宽度:{innerWidth}px</p>
</div>

<style>
	.container[data-layout="mobile"] {
		flex-direction: column;
	}

	.container[data-layout="tablet"] {
		flex-direction: row;
		flex-wrap: wrap;
	}

	.container[data-layout="desktop"] {
		flex-direction: row;
	}
</style>

实战:键盘快捷键

利用 <svelte:window> 的键盘事件监听实现快捷键。

<script>
	let showHelp = $state(false);

	function handleKeydown(event) {
		// Cmd+/ (Mac) 或 Ctrl+/ (Windows) 切换帮助面板
		if ((event.metaKey || event.ctrlKey) && event.key === '/') {
			event.preventDefault();
			showHelp = !showHelp;
		}

		// ESC 关闭
		if (event.key === 'Escape') {
			showHelp = false;
		}
	}
</script>

<svelte:window onkeydown={handleKeydown} />

<h1>快捷键示例</h1>
<p>按 Ctrl+/ 或 Cmd+/ 打开帮助,ESC 关闭</p>

{#if showHelp}
	<div style="position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); padding: 20px; background: white; border: 1px solid #ccc; border-radius: 8px; box-shadow: 0 4px 12px rgba(0,0,0,0.15);">
		<h3>快捷键帮助</h3>
		<ul>
			<li>Ctrl+/ - 打开/关闭帮助</li>
			<li>ESC - 关闭帮助</li>
		</ul>
		<button onclick={() => showHelp = false}>关闭</button>
	</div>
{/if}

本节回顾

  • <svelte:window> 监听窗口事件和绑定窗口属性(scrollY、innerWidth 等)
  • <svelte:document> 监听 document 事件(visibilitychange 等)和绑定文档属性
  • <svelte:body> 监听 body 事件(mouseenter/mouseleave 等)
  • 这三个元素只能出现在组件顶层,组件卸载时自动清理监听器
  • scrollYscrollX 是可写的,其他窗口属性都是只读
  • 初始渲染不会自动滚动到 scrollY 绑定值,需要手动调用 scrollTo()