Next.js
مسیریاب app
برنامه تان را بسیازید
مسیریابی Routing
طرح بندی ها و قالب ها

طرح بندی ها و قالب ها

فایل‌های خاص layout.js و template.js به شما این امکان را می‌دهند تا رابط کاربری مشترک بین چندین مسیر (routes) ایجاد کنید. این صفحه شما را در نحوه و زمان استفاده از این فایل‌های خاص راهنمایی می‌کند.

طرح بندی ها Layouts

طرح بندی، رابط کاربری است که بین چندین مسیر به اشتراک گذاشته می‌شود. طرح بندی ها در هنگام پیمایش، وضعیت را حفظ می‌کنند، تعاملی باقی می‌مانند و دوباره رندر نمی‌شوند. طرح بندی ها همچنین می‌توانند به صورت تو در تو قرار بگیرند (nested).

شما می‌توانید با پیش‌فرض گرفتن خروجی یک کامپوننت React از یک فایل layout.js یک طرح بندی تعریف کنید. این کامپوننت باید یک prop به نام children بپذیرد که در زمان رندر با یک طرح بندی فرزند (در صورت وجود) یا یک صفحه پر خواهد شد.

به عنوان مثال، این طرح بندی با صفحات /dashboard و /dashboard/settings به اشتراک گذاشته خواهد شد:


فایل ویژه layout.jsفایل ویژه layout.js
app/dashboard/layout.tsx
export default function DashboardLayout({
	children, // will be a page or nested layout
}: {
	children: React.ReactNode
}) {
	return (
		<section>
			{/* Include shared UI here e.g. a header or sidebar */}
			<nav></nav>
 
			{children}
		</section>
	)
}

طرح بندی ریشه (الزامی)

طرح بندی ریشه (root layout) در بالاترین سطح پوشه app تعریف می‌شود و برای همه مسیرها اعمال می‌شود. این طرح بندی الزامی است و باید شامل تگ‌های html و body باشد و این امکان را به شما می‌دهد تا HTML اولیه‌ای که از سرور برگردانده می‌شود را ویرایش کنید.

app/layout.tsx
export default function RootLayout({
	children,
}: {
	children: React.ReactNode
}) {
	return (
		<html lang="en">
			<body>
				{/* Layout UI */}
				<main>{children}</main>
			</body>
		</html>
	)
}

تو در تو کردن طرح بندی ها

به طور پیش‌فرض، طرح بندی ها در سلسله‌مراتب پوشه‌ها تو در تو هستند، به این معنی که آن‌ها طرح بندی های فرزند را از طریق prop به نام children خود دربر می‌گیرند. شما می‌توانید با اضافه کردن فایل layout.js درون بخش‌های خاص مسیر (پوشه‌ها) طرح بندی ها را تو در تو کنید.

به عنوان مثال، برای ایجاد یک طرح بندی برای مسیر /dashboard، یک فایل layout.js جدید در پوشه dashboard اضافه کنید:


طرح بندی تو در توطرح بندی تو در تو
app/dashboard/layout.tsx
export default function DashboardLayout({
	children,
}: {
	children: React.ReactNode
}) {
	return <section>{children}</section>
}

اگر بخواهید این دو طرح بندی بالا را با هم ترکیب کنید، طرح بندی ریشه (app/layout.js) طرح بندی داشبورد (app/dashboard/layout.js) را دربر می‌گیرد و طرح بندی داشبورد نیز بخش‌های مسیر داخل پوشه app/dashboard/* را دربر خواهد گرفت.

این دو طرح بندی (layout) به این صورت تو در تو خواهند بود:


طرح بندی های تو در توطرح بندی های تو در تو

خوب است بدانید:

  • برای طرح بندی ها می‌توانید از پسوندهای .js، .jsx یا .tsx استفاده کنید.
  • فقط طرح بندی ریشه (root layout) می‌تواند تگ‌های <html> و <body> را داشته باشد.
  • هنگامی که یک فایل layout.js و page.js در یک پوشه تعریف شوند، طرح بندی (layout)، صفحه را دربر می‌گیرد .(warp)
  • طرح بندی ها به طور پیش‌فرض کامپوننت‌های سمت سرور Server Components هستند، اما می‌توان آن‌ها را به عنوان کامپوننت‌های سمت کلاینت Client Component تنظیم کرد.
  • طرح بندی ها می‌توانند داده‌ها را دریافت کنند. Data Fetching
  • انتقال داده بین یک طرح بندی والد و فرزندان آن امکان‌پذیر نیست. با این حال، می‌توانید داده‌های مشابه را در یک مسیر بیش از یک بار دریافت کنید و React به طور خودکار درخواست‌ها را بدون تأثیر بر عملکرد، تکراری‌زدایی می‌کند (dedupe).
  • طرح بندی ها به pathname دسترسی ندارند (بیشتر بدانید). اما کامپوننت‌های سمت سمت کلاینت (Client Components) که وارد شده‌اند، می‌توانند با استفاده از هوک usePathname به pathname دسترسی پیدا کنند.
  • طرح بندی ها به بخش‌های مسیر (route segments) پایین‌تر از خود دسترسی ندارند. برای دسترسی به تمام بخش‌های مسیر، می‌توانید از useSelectedLayoutSegment یا useSelectedLayoutSegments در یک کامپوننت سمت کلاینت (Client Component) استفاده کنید.
  • شما می‌توانید از گروه‌های مسیر (Route Groups) برای انتخاب بخش‌های خاص مسیر جهت استفاده یا عدم استفاده از طرح بندی های به اشتراک گذاشته شده، استفاده کنید.
  • شما می‌توانید از گروه‌های مسیر (Route Groups) برای ایجاد چندین طرح بندی ریشه استفاده کنید. یک مثال: در اینجا ببینید.
  • مهاجرت از دایرکتوری pages: طرح بندی ریشه جایگزین فایل‌های _app.js و _document.js می‌شود. راهنمای مهاجرت را ببینید.

قالب ها Templates

قالب‌ها شبیه طرح بندی ها هستند، زیرا یک طرح بندی فرزند یا صفحه را در بر می‌گیرند. برخلاف طرح بندی ها که در کل مسیرها باقی می‌مانند و وضعیت را حفظ می‌کنند، قالب‌ها برای هر فرزند خود در هنگام پیمایش یک نمونه جدید ایجاد می‌کنند. این یعنی زمانی که کاربر بین مسیرهایی که یک قالب مشترک دارند جابجا می‌شود، یک نمونه جدید از فرزند mount می‌شود، المان‌های DOM دوباره ساخته می‌شوند، حالت در کامپوننت‌های سمت کلاینت حفظ نمی‌شود و effectها دوباره همگام‌سازی می‌شوند.

در برخی موارد که به این رفتارهای خاص نیاز دارید، قالب‌ها نسبت به طرح بندی ها گزینه مناسب‌تری هستند. برای مثال:

  • همگام‌سازی مجدد useEffect هنگام پیمایش.
  • بازنشانی حالت یک کامپوننت فرزند سمت کاربر در هنگام پیمایش.

یک قالب را می‌توان با پیش‌فرض گرفتن خروجی یک کامپوننت React از یک فایل template.js تعریف کرد. این کامپوننت باید یک prop به نام children بپذیرد.


فایل ویژه template.jsفایل ویژه template.js
app/template.tsx
export default function Template({ children }: { children: React.ReactNode }) {
	return <div>{children}</div>
}

از نظر تو در تو شدن، template.js بین یک طرح بندی و فرزندانش رندر می‌شود. در اینجا خروجی ساده شده است:

Output
<Layout>
	{/* Note that the template is given a unique key. */}
	<Template key={routeParam}>{children}</Template>
</Layout>

مثال ها

Metadata

شما می‌توانید تگ‌های HTML بخش <head> مانند title و meta را با استفاده از Metadata APIs تغییر دهید.

Metadata را می‌توان با خروجی گرفتن یک metadata object یا تابع generateMetadata از یک فایل layout.js یا page.js تعریف کرد.

app/page.tsx
import { Metadata } from 'next'
 
export const metadata: Metadata = {
	title: 'Next.js',
}
 
export default function Page() {
	return '...'
}

خوب است بدانید: شما نباید تگ‌های <head> مانند <title> و <meta> را به صورت دستی به طرح بندی های ریشه (root layouts) اضافه کنید. در عوض، از Metadata API استفاده کنید که به طور خودکار نیازمندی‌های پیشرفته مانند استریم کردن و حذف موارد تکراری از تگ‌های <head> را مدیریت می‌کند.

در مورد گزینه های metadata در مرجع API بیشتر بدانید.

لینک‌های فعال در نوار پیمایش

می‌توانید از هوک usePathname() برای تشخیص اینکه آیا یک لینک پیمایش فعال است یا خیر استفاده کنید.

از آنجایی که usePathname() یک هوک کلاینت است، باید لینک‌های پیمایش را درون یک کامپوننت سمت کاربر (Client Component) استخراج کنید تا بتوانید آن را در طرح بندی یا قالب خود وارد کنید:

app/ui/nav-links.tsx
'use client'
 
import { usePathname } from 'next/navigation'
import Link from 'next/link'
 
export function NavLinks() {
	const pathname = usePathname()
 
	return (
		<nav>
			<Link
				className={`link ${pathname === '/' ? 'active' : ''}`}
				href="/"
			>
				Home
			</Link>
 
			<Link
				className={`link ${pathname === '/about' ? 'active' : ''}`}
				href="/about"
			>
				About
			</Link>
		</nav>
	)
}
app/layout.tsx
import { NavLinks } from '@/app/ui/nav-links'
 
export default function Layout({ children }: { children: React.ReactNode }) {
	return (
		<html lang="en">
			<body>
				<NavLinks />
				<main>{children}</main>
			</body>
		</html>
	)
}