Page ба Layout
Өмнөх хичээлд page.tsx файл үүсгэж хуудас нэмэхийг сурлаа. Одоо layout гэдэг ойлголтыг судална. Layout бол хуудсуудын нийтлэг бүрхүүл — navbar, footer зэргийг нэг удаа бичиж бүх хуудасд автоматаар харуулах боломжийг олгодог.
layout.tsx гэж юу вэ?
layout.tsx бол хүүхэд хуудсуудаа children prop-оор хүлээн авч бүрхэн харуулдаг component. Аль ч route-д layout.tsx нэмж болно:
app/
├── layout.tsx ← Бүх хуудасд нийтлэг (root layout)
├── page.tsx ← / хуудас
└── courses/
├── layout.tsx ← /courses/* хуудасд нийтлэг
└── page.tsx ← /courses хуудас
Root layout
app/layout.tsx бол заавал байх ёстой файл — бүх хуудасны гадаад бүрхүүл. HTML бүтцийг энд тодорхойлдог:
// app/layout.tsx
import type { Metadata } from "next";
import { Geist, Geist_Mono } from "next/font/google";
import "./globals.css";
const geistSans = Geist({ subsets: ["latin"], variable: "--font-geist-sans" });
const geistMono = Geist_Mono({
subsets: ["latin"],
variable: "--font-geist-mono",
});
export const metadata: Metadata = {
title: "ulaanbaatar.app",
description: "Монголын кодчиллын платформ",
};
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="mn">
<body className={`${geistSans.variable} ${geistMono.variable}`}>
<nav>Navbar энд</nav>
{children}
<footer>Footer энд</footer>
</body>
</html>
);
}
children гэдэг нь тухайн URL-д тохирох page.tsx-н гаралт. /about хаягаар ороход children = AboutPage-н гаралт болно.
Nested layout — давхар layout
courses/ директорт өөрийн layout.tsx нэмж болно. Энэ layout нь root layout-н дотор render хийгдэнэ:
// app/courses/layout.tsx
export default function CoursesLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<div className="flex">
<aside>
{/* Курсуудын sidebar */}
<p>Sidebar энд</p>
</aside>
<main className="flex-1">{children}</main>
</div>
);
}
Одоо /courses болон /courses/javascript хаягаар ороход аль аль нь энэ sidebar-тай харагдана. /about хаягаар ороход sidebar харагдахгүй — зөвхөн root layout ажиллана.
Давхарлалт ийм харагдана:
RootLayout
└── CoursesLayout
└── page.tsx (CoursePage эсвэл LessonPage)
page.tsx ба layout.tsx-н ялгаа
| | page.tsx | layout.tsx |
| --------------- | -------------------------- | --------------------------- |
| Зориулалт | Хуудасны агуулга | Бүрхүүл, навигаци |
| children prop | Байхгүй | Заавал байна |
| Дахин render | URL солигдоход | Дахин render хийгдэхгүй |
| Заавал эсэх | Тийм (хуудас болохын тулд) | Үгүй |
Layout дахин render хийгдэхгүй гэдэг нь маш чухал — хэрэглэгч /courses-с /courses/javascript руу шилжихэд layout хэвээр үлдэж, зөвхөн children солигдоно. Энэ нь гүйцэтгэлийг сайжруулдаг.
metadata экспорт
Хуудас бүр metadata объект экспортолж SEO мэдээллийг тохируулж болно:
// app/courses/page.tsx
import type { Metadata } from "next";
export const metadata: Metadata = {
title: "Сургалтууд | ulaanbaatar.app",
description: "JavaScript, React, Next.js болон бусад курсууд",
};
export default function CoursesPage() {
return <h1>Сургалтууд</h1>;
}
Dynamic хуудасд generateMetadata функц ашиглана:
// app/courses/[courseSlug]/page.tsx
import type { Metadata } from "next";
interface Props {
params: Promise<{ courseSlug: string }>;
}
export async function generateMetadata({ params }: Props): Promise<Metadata> {
const { courseSlug } = await params;
return {
title: `${courseSlug} | ulaanbaatar.app`,
};
}
export default async function CoursePage({ params }: Props) {
const { courseSlug } = await params;
return <h1>{courseSlug}</h1>;
}
Дараагийн хичээлд:
Хуудсуудын хооронд шилжихэд <Link> component ашиглана. Энгийн <a> тэгийн оронд <Link> ашиглах нь яагаад чухал болохыг ойлгоно.