淺層路由
當您在 SvelteKit 應用程式中導覽時,您會建立歷史記錄項目。點擊「上一頁」和「下一頁」按鈕會瀏覽此項目清單,重新執行任何 load
函式,並在必要時替換頁面元件。
有時,建立不導覽的歷史記錄項目會很有用。例如,您可能想要顯示一個模態對話框,使用者可以透過返回來關閉它。這在行動裝置上尤其重要,因為滑動手勢通常比直接與 UI 互動更自然。在這些情況下,與歷史記錄項目沒有關聯的模態可能會令人感到沮喪,因為使用者可能會嘗試向後滑動以關閉它,卻發現自己到了錯誤的頁面。
SvelteKit 使用 pushState
和 replaceState
函式使這成為可能,這些函式允許您將狀態與歷史記錄項目相關聯,而無需導覽。例如,要實作歷史記錄驅動的模態
<script>
import { pushState } from '$app/navigation';
import { page } from '$app/stores';
import Modal from './Modal.svelte';
function showModal() {
pushState('', {
showModal: true
});
}
</script>
{#if $page.state.showModal}
<Modal close={() => history.back()} />
{/if}
可以透過返回(取消設定 $page.state.showModal
)或透過與之互動以導致 close
回呼執行的來關閉模態,這將以程式方式返回。
API
pushState
的第一個參數是 URL,相對於目前的 URL。若要保持在目前的 URL,請使用 ''
。
第二個參數是新的頁面狀態,可以透過 頁面儲存 作為 $page.state
存取。您可以透過宣告 App.PageState
介面(通常在 src/app.d.ts
中)使頁面狀態具有型別安全。
若要設定頁面狀態而不建立新的歷史記錄項目,請使用 replaceState
而不是 pushState
。
為路由載入資料
在淺層路由時,您可能想要在目前頁面內呈現另一個 +page.svelte
。例如,點擊照片縮圖可能會彈出詳細檢視,而不會導覽至照片頁面。
為了使此功能運作,您需要載入 +page.svelte
所期望的資料。執行此操作的便捷方法是在 <a>
元素的 click
處理常式中使用 preloadData
。如果該元素(或父元素)使用 data-sveltekit-preload-data
,則已要求資料,並且 preloadData
將重複使用該請求。
<script>
import { preloadData, pushState, goto } from '$app/navigation';
import { page } from '$app/stores';
import Modal from './Modal.svelte';
import PhotoPage from './[id]/+page.svelte';
let { data } = $props();
</script>
{#each data.thumbnails as thumbnail}
<a
href="/photos/{thumbnail.id}"
onclick={async (e) => {
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);
}
}}
>
<img alt={thumbnail.alt} src={thumbnail.src} />
</a>
{/each}
{#if $page.state.selected}
<Modal onclose={() => history.back()}>
<!-- pass page data to the +page.svelte component,
just like SvelteKit would on navigation -->
<PhotoPage data={$page.state.selected} />
</Modal>
{/if}
注意事項
在伺服器端呈現期間,$page.state
始終是一個空物件。使用者登陸的第一個頁面也是如此 — 如果使用者重新載入頁面(或從另一個文件返回),在導覽之前不會套用狀態。
淺層路由是一項需要 JavaScript 才能運作的功能。使用時請注意,並嘗試在 JavaScript 不可用的情況下考慮合理的後備行為。