iT邦幫忙

2024 iThome 鐵人賽

DAY 17
0
Modern Web

Svelte 的奇妙冒險系列 第 17

[Svelte 的奇妙冒險] Day 17 - SvelteKit 中的路由 (2)

  • 分享至 

  • xImage
  •  

今天來繼續介紹 SvelteKit 的路由。

+layout.svelte

+layout.svlete 主要是來建立頁面之間共用的佈局,像是如果我有一個 header 長這樣:

<nav>
	<a href="/">Home</a>
	<a href="/day16">day16</a>
	<a href="/day17">day17</a>
</nav>

在 SvelteKit 中一般情況下,可以直接使用 <a href='' /> 來作為 redirect 的 component ,不用像其他框架使用 <Link /> 之類的特別 component。

當然不會想要每一個 +page.svelte 都手動加上這些東西,那這時我們只要放在 src/routes/+layout.svelte 就可以讓 src/routes/** 之後的所有 +page.svelte 都可以擁有一樣的佈局

<!-- in src/routes/+layout.svelte-->
<nav>
	<a href="/">Home</a>
	<a href="/day16">day16</a>
	<a href="/day17">day17</a>
</nav>

<slot/>

這個 <slot /> 是 Svelte 4 讓我們可以把 component 傳進一個 component裡的方式,就跟我們在 Day 10 中使用 {#snippet} 加上 {@render children} ,總之在這個例子中 +page.svelte 的東西會被丟到 <slot/> 的位置。

其實在 +layout.svelte 也可以使用 $props 取的 children ,但這裡還是先按照 SvelteKit 官方文件的使用方式,畢竟 Svelte 5 還是在 preview 階段。

新增一下src/routes/day17/+page.svelte

<h1>Day17</h1>

之後就可以來看一下我們現在畫面:

會發現不管到哪個頁面都可以顯示出我們的 header 。

那如果我新增一個 src/routes/day17/+layout.svelte 呢?

<nav>
	<a href="/">Home</a>
	<a href="/day16">day16</a>
</nav>

<slot />

所以如果我有一群 nested 的 +layout.svelte ,在預設情況下他們會堆疊起來。也就是說src/routes/+layout.svelte 是影響到 src/routes/**/+page.sveltesrc/routes/day17/+layout.svelte 就是會影響到 src/routes/day17/**/+page.svelte

以這個例子來說,如果有個 day17/foo/+page.svelte 他也會同時出現兩個 nav

<h1>src/routes/day17/foo/+page.svelte</h1>

+layout.ts

+page.ts 一樣我們也可以在這裡使用 load function ,讓同一個 scope 的頁面都可以獲得一樣的資料,而且跟 +layout.svelte 的邏輯類似的是 Svelte 會自動幫我們把這些 data 給 merge 在一起,而且當然也可以使用 params

// in src/routes/+layout.ts
import type { LayoutLoad } from './$types';

export const load: LayoutLoad = () => {
	return {
		title: 'Hello world! ',
		content: 'Welcome to our blog. Lorem ipsum dolor sit amet...'
	};
};

// in src/routes/day17/+layout.ts
import type { LayoutLoad } from './$types';

export const load: LayoutLoad = ({ params }) => {
	return {
		name: params?.name || 'foo',
		title: '[Day 17] Hello world! '
	};
};

<!-- in src/routes/day17/[name]/+page.svelte -->

<script lang="ts">
	import { page } from '$app/stores';
	import type { PageData } from './$types';
	interface Props {
		data: PageData;
	}

	let { data }: Props = $props();
	console.log('data', $page.params, data);
</script>

<h1>{$page.params.name}</h1>

會發現 title 被覆蓋成 src/routes/day17/+layout.ts 的內容了,且 name 也可以正確被加上去。

就跟在 +page.ts 一樣,我們可以在 +layout.ts 去設定 ssr 以及 csr 等等的參數,那他的影響範圍的邏輯就跟其他 +layout 的道理是一樣的。


參考資料

source code

https://github.com/toddLiao469469/30days-for-svelte5/tree/main/src/routes/day17


上一篇
[Svelte 的奇妙冒險] Day 16 - SvelteKit 中的路由
下一篇
[Svelte 的奇妙冒險] Day 18 - SvelteKit 中的路由 (3)
系列文
Svelte 的奇妙冒險30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言