当你浏览 SvelteKit 应用时,你会创建历史记录条目。点击后退和前进按钮会遍历此条目列表,重新运行任何 `加载` 函数,并在必要时替换页面组件。 有时,在不导航的情况下创建历史记录条目很有用。*无需*导航。例如,您可能希望显示一个用户可以通过导航返回来关闭的模态对话框。这在移动设备上尤其有价值,因为在移动设备上,滑动手势通常比直接与 UI 交互更自然。在这些情况下,一个与历史记录条目*不相关*的模态可能会引起用户的挫败感,因为用户可能会尝试向后滑动以关闭它,却发现自己在错误的页面上。 SvelteKit 通过`pushState`和`replaceState`函数实现这一点,这些函数允许您在不进行导航的情况下将状态与历史记录条目关联。例如,要实现由历史记录驱动的模态: ```svelte {#if page.state.showModal} history.back()} /> {/if} ``` 模态窗口可以通过返回操作(取消设置 `page.state.showModal`)或通过与之交互以触发 `close` 回调的方式来关闭,这将程序化地返回上一页。 ## API 第一个参数是相对于当前 URL 的 URL,要保持在当前 URL,请使用`''`。 第二个参数是新的页面状态,可以通过[页面对象]($app-state#page)作为`page.state`访问。您可以通过声明一个[`App.PageState`](types#PageState)接口(通常在`src/app.d.ts`中)来使页面状态类型安全。 为设置页面状态而不创建新的历史记录条目,请使用`replaceState`代替`pushState`。 > \[!旧版\] 从 `$app/state` 添加了 `page.state` 到 SvelteKit 2.12。如果您使用的是更早的版本或使用 Svelte 4,请使用从 `$app/stores` 的 `$page.state` 代替。 ## 加载数据以供路线使用 当进行浅层路由时,您可能希望在当前页面内渲染另一个 `+page.svelte`。例如,点击照片缩略图可以弹出详细视图,而无需导航到照片页面。 为此工作,您需要加载 `+page.svelte` 所期望的数据。一种方便的方法是在一个 `` 元素的 `click` 处理器中使用 [`preloadData`]($app-navigation#preloadData)。如果该元素(或其父元素)使用了 [`data-sveltekit-preload-data`](link-options#data-sveltekit-preload-data),则数据已经被请求,并且 `preloadData` 将重用该请求。 ```svelte {#each data.thumbnails as thumbnail} { if (innerWidth < 640 // bail if the screen is too small || e.shiftKey // or the link is opened in a new window || e.metaKey || e.ctrlKey // or a new tab (mac: metaKey, win/linux: ctrlKey) // should also consider clicking with a mouse scroll wheel ) return; // prevent navigation e.preventDefault(); const { href } = e.currentTarget; // run `load` functions (or rather, get the result of the `load` functions // that are already running because of `data-sveltekit-preload-data`) const result = await preloadData(href); if (result.type === 'loaded' && result.status === 200) { pushState(href, { selected: result.data }); } else { // something bad happened! try navigating goto(href); } }} > {thumbnail.alt} {/each} {#if page.state.selected} history.back()}> {/if} ``` ## 注意事项 在服务器端渲染期间,`page.state`始终是一个空对象。对于用户首次访问的页面也是如此——如果用户刷新页面(或从另一个文档返回),状态将*不会*应用,直到他们进行导航。 浅层路由是一个需要 JavaScript 才能工作的功能。使用时请谨慎,并尝试考虑在 JavaScript 不可用时的合理回退行为。