Skip to main content

Svelte: $page/state

SvelteKit 中,import { page } from '$app/state'; 是 SvelteKit 2.12+ 版本引入的新方式,用于获取当前页面的 只读响应式状态对象(read-only reactive object)。

它是什么?

  • page 是一个全局可用的响应式对象(基于 Svelte 5 的 runes 系统,使用 $state.raw 实现响应性)。
  • 它提供当前页面的各种信息,包括 URL、路由参数、加载的数据、HTTP 状态码等。
  • 可以在 任何组件(包括 layout、page、甚至嵌套组件)中直接导入和使用,不需要再用旧的 $page store($app/stores)。
  • 它是 只读 的,不能直接修改,但它的属性变化时会自动触发组件的响应式更新(例如导航到新页面时)。

page 对象的主要属性包括:

  • page.url:一个 URL 对象,包含当前页面的完整 URL 信息。
  • page.params:路由动态参数(如 /blog/[slug] 中的 slug)。
  • page.data:从 +page.js / +layout.jsload 函数加载的数据。
  • page.route:当前路由信息(包含 id)。
  • page.status:HTTP 状态码(例如 200、404 等)。
  • page.state:通过 pushState / replaceState 设置的浅层状态(shallow routing)。

重点:page.url.pathname

  • page.url 是浏览器原生的 URL 对象。
  • page.url.pathname 返回当前页面的路径部分(不包含域名、查询参数等),例如:
    • 访问 https://example.com/blog/123 时,page.url.pathname 的值是 "/blog/123"
    • 访问首页时,通常是 "/"

这个属性常用于:

  • 判断当前页面路径,实现高亮导航菜单。
  • 根据路径做条件渲染。
  • 监听路由变化(结合 Svelte 5 的 runes 如 $derived$effect)。

实际举例

示例 1:基础使用(在布局中高亮当前导航)

src/routes/+layout.svelte 中:

<script>
import { page } from '$app/state';
let { children } = $props(); // Svelte 5 runes 语法
</script>

<nav>
<a href="/" aria-current={page.url.pathname === '/'}>首页</a>
<a href="/about" aria-current={page.url.pathname === '/about'}>关于</a>
<a href="/blog" aria-current={page.url.pathname.startsWith('/blog')}>博客</a>
</nav>

{@render children()}

效果:当用户在不同页面导航时,当前链接会自动加上 aria-current="true"(可配合 CSS 高亮)。

示例 2:在页面组件中显示当前路径

在任意 +page.svelte 中:

<script>
import { page } from '$app/state';
</script>

<p>当前路径:{page.url.pathname}</p>

{#if page.url.pathname === '/dashboard'}
<h1>欢迎来到仪表盘</h1>
{:else}
<h1>其他页面</h1>
{/if}

示例 3:结合 Svelte 5 runes 做派生值(更推荐的响应式写法)

<script>
import { page } from '$app/state';

// 派生当前是否在博客页面
let isBlogPage = $derived(page.url.pathname.startsWith('/blog'));

// 或者提取路径的最后一段
let currentSlug = $derived(page.url.pathname.split('/').pop() || '');
</script>

{#if isBlogPage}
<p>你在浏览博客,slug: {currentSlug}</p>
{/if}

示例 4:监听路径变化(使用 $effect)

<script>
import { page } from '$app/state';

$effect(() => {
console.log('路径发生变化:', page.url.pathname);
// 可以在这里做一些副作用,比如埋点、更新本地状态等
});
</script>

注意事项

  • 响应性page 是响应式的,页面导航(客户端路由)时会自动更新。但在服务器渲染(SSR)首次加载时,某些属性可能有初始值限制。
  • 旧版本兼容:如果你用的是较旧的 SvelteKit,可能还是用 import { page } from '$app/stores'; 并以 $page.url.pathname 的形式访问(带 $ 前缀的 store)。新版推荐 $app/state
  • TypeScript:可以配合 import type { Page } from '@sveltejs/kit'; 来获得完整类型提示。
  • 不能修改page 是只读的,如果你需要修改 URL 状态,请用 $app/navigation 中的 pushState / replaceState

这个 page 对象极大地方便了在组件树任意位置获取路由信息,而不需要层层传递 props。