Layouts และ Navigation
ใน React Router คุณสร้าง layout ด้วย component ที่ render <Outlet /> เพื่อให้ child routes แสดงผลตรงนั้น ส่วน Next.js App Router ใช้ไฟล์ layout.tsx ที่ wrap {children} ให้อัตโนมัติ SvelteKit ใช้แนวคิดเดียวกันผ่านไฟล์ +layout.svelte — วาง {@render children()} ไว้ตรงไหน child pages ก็จะแสดงผลตรงนั้น และ layout จะ persist ข้ามการนำทางโดยไม่ unmount
+layout.svelte กับ Outlet / layout.tsx
หัวข้อที่มีชื่อว่า “+layout.svelte กับ Outlet / layout.tsx”// src/routes/_layout.tsx (Remix) หรือ app/layout.tsx (Next.js)export default function RootLayout({ children }) { return ( <html> <body> <nav> <a href="/">Home</a> <a href="/about">About</a> <a href="/blog">Blog</a> </nav> <main>{children}</main> </body> </html> );}<!-- src/routes/+layout.svelte --><script> let { children } = $props();</script>
<nav> <a href="/">Home</a> <a href="/about">About</a> <a href="/blog">Blog</a></nav>
<main> {@render children()}</main>จุดสำคัญ: {@render children()} ของ SvelteKit ทำหน้าที่เหมือน {children} ของ Next.js และ <Outlet /> ของ React Router — เป็นที่ที่ child page จะถูก inject เข้ามา ไฟล์ +layout.svelte ใดก็ตามที่วางอยู่ใน src/routes/ จะ wrap ทุก page ภายใต้ directory นั้น
การนำทางด้วย <a href> ธรรมดา
หัวข้อที่มีชื่อว่า “การนำทางด้วย <a href> ธรรมดา”ใน React คุณต้องใช้ <Link> component จาก react-router หรือ Next.js เพื่อ client-side navigation การใช้ <a> ธรรมดาจะทำให้ full-page reload SvelteKit จัดการสิ่งนี้ให้คุณ — ใช้ <a href> ธรรมดาได้เลย โดย SvelteKit จะ intercept การคลิกแล้วทำ client-side navigation ให้อัตโนมัติ
// React Router / Next.jsimport { Link, useLocation } from 'react-router-dom';// หรือ import Link from 'next/link';// หรือ import { usePathname } from 'next/navigation';
function Nav() { const location = useLocation(); return ( <nav> <Link to="/" className={location.pathname === '/' ? 'active' : ''}> Home </Link> <Link to="/about" className={location.pathname === '/about' ? 'active' : ''}> About </Link> </nav> );}<script> import { page } from '$app/state';</script>
<nav> <a href="/" class:active={page.url.pathname === '/'}> Home </a> <a href="/about" class:active={page.url.pathname === '/about'}> About </a></nav>
<style> .active { font-weight: bold; }</style>ไม่มี <Link> component ไม่มี useLocation hook — แค่ <a> ธรรมดาพร้อม $app/state สำหรับอ่าน URL ปัจจุบัน
$app/state และ page store
หัวข้อที่มีชื่อว่า “$app/state และ page store”page จาก $app/state คือ reactive object ที่ให้ข้อมูล route ปัจจุบัน เทียบได้กับ useLocation() + useParams() ใน React Router หรือ usePathname() + useSearchParams() ใน Next.js
<script> import { page } from '$app/state';</script>
<p>เส้นทางปัจจุบัน: {page.url.pathname}</p><p>URL params: {JSON.stringify(page.params)}</p><p>Search: {page.url.search}</p>ข้อมูลสำคัญที่ page ให้:
| Property | เทียบเท่าใน React |
|---|---|
page.url.pathname | useLocation().pathname / usePathname() |
page.params | useParams() |
page.url.searchParams | useSearchParams() |
page.data | ข้อมูลที่ load function ส่งกลับมา |
page.status | HTTP status code ของหน้านี้ |
Nested layouts
หัวข้อที่มีชื่อว่า “Nested layouts”Layout ซ้อนกันได้ตามลำดับชั้น directory — เหมือนกับ Next.js App Router ทุกประการ
flowchart TB routes(["src/routes/"]) routes --> rootLayout["+layout.svelte (root layout — nav + footer)"] routes --> rootPage["+page.svelte → /"] routes --> dashboard["dashboard/"] dashboard --> dashLayout["+layout.svelte (dashboard layout — sidebar)"] dashboard --> dashPage["+page.svelte → /dashboard"] dashboard --> settings["settings/"] settings --> settingsPage["+page.svelte → /dashboard/settings"]
/dashboard/settings จะได้รับทั้ง root layout และ dashboard layout ซ้อนกัน โดยไม่ต้องกำหนด config ใด ๆ เพิ่มเติม