الصفحات والتخطيطات
نوصي بقراءة صفحات أساسيات التوجيه وتحديد المسارات قبل المتابعة.
تسمح لك الملفات الخاصة layout.js، page.js، و template.js بإنشاء واجهة مستخدم لـ مسار. سيرشدك هذا الصفحة حول كيفية ومتى تستخدم هذه الملفات الخاصة.
الصفحات
الصفحة هي واجهة مستخدم فريدة لمسار. يمكنك تعريف صفحة عن طريق تصدير مكون افتراضي من ملف page.js
.
على سبيل المثال، لإنشاء صفحتك index
، أضف ملف page.js
داخل دليل app
:

// `app/page.tsx` هو واجهة المستخدم لمسار `/`
export default function Page() {
return <h1>مرحبًا، الصفحة الرئيسية!</h1>
}
// `app/page.js` هو واجهة المستخدم لمسار `/`
export default function Page() {
return <h1>مرحبًا، الصفحة الرئيسية!</h1>
}
ثم، لإنشاء صفحات إضافية، أنشئ مجلدًا جديدًا وأضف ملف page.js
بداخله. على سبيل المثال، لإنشاء صفحة لمسار /dashboard
، أنشئ مجلدًا جديدًا باسم dashboard
، وأضف ملف page.js
بداخله:
// `app/dashboard/page.tsx` هو واجهة المستخدم لمسار `/dashboard`
export default function Page() {
return <h1>مرحبًا، صفحة لوحة التحكم!</h1>
}
// `app/dashboard/page.js` هو واجهة المستخدم لمسار `/dashboard`
export default function Page() {
return <h1>مرحبًا، صفحة لوحة التحكم!</h1>
}
جيد أن تعرف:
- يمكن استخدام امتدادات الملفات
.js
أو.jsx
أو.tsx
للصفحات.- الصفحة هي دائمًا ورقة لـ شجرة المسار الفرعية.
- ملف
page.js
مطلوب لجعل جزء المسار قابلًا للوصول علنًا.- الصفحات هي مكونات خادم (Server Components) افتراضيًا، ولكن يمكن تعيينها كـ مكون عميل (Client Component).
- يمكن للصفحات جلب البيانات. راجع قسم جلب البيانات لمزيد من المعلومات.
التخطيطات
التخطيط هو واجهة مستخدم مشتركة بين مسارات متعددة. عند التنقل، تحافظ التخطيطات على الحالة، تبقى تفاعلية، ولا تعيد التصيير. يمكن أيضًا تداخل التخطيطات.
يمكنك تعريف تخطيط عن طريق تصدير مكون React افتراضي من ملف layout.js
. يجب أن يقبل المكون خاصية children
التي سيتم ملؤها بتخطيط فرعي (إذا وجد) أو صفحة أثناء التصيير.
على سبيل المثال، سيكون التخطيط مشتركًا مع صفحات /dashboard
و /dashboard/settings
:

export default function DashboardLayout({
children, // سيكون صفحة أو تخطيط متداخل
}: {
children: React.ReactNode
}) {
return (
<section>
{/* ضع واجهة المستخدم المشتركة هنا مثل رأس أو شريط جانبي */}
<nav></nav>
{children}
</section>
)
}
export default function DashboardLayout({
children, // سيكون صفحة أو تخطيط متداخل
}) {
return (
<section>
{/* ضع واجهة المستخدم المشتركة هنا مثل رأس أو شريط جانبي */}
<nav></nav>
{children}
</section>
)
}
التخطيط الجذري (مطلوب)
يتم تعريف التخطيط الجذري في المستوى الأعلى من دليل app
وينطبق على جميع المسارات. هذا التخطيط مطلوب ويجب أن يحتوي على علامات html
و body
، مما يسمح لك بتعديل HTML الأولي المرسل من الخادم.
export default function RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<html lang="en">
<body>
{/* واجهة مستخدم التخطيط */}
<main>{children}</main>
</body>
</html>
)
}
export default function RootLayout({ children }) {
return (
<html lang="en">
<body>
{/* واجهة مستخدم التخطيط */}
<main>{children}</main>
</body>
</html>
)
}
تداخل التخطيطات
افتراضيًا، التخطيطات في تسلسل المجلدات متداخلة، مما يعني أنها تغلف التخطيطات الفرعية عبر خاصية children
. يمكنك تداخل التخطيطات عن طريق إضافة layout.js
داخل أجزاء مسار محددة (مجلدات).
على سبيل المثال، لإنشاء تخطيط لمسار /dashboard
، أضف ملف layout.js
جديد داخل مجلد dashboard
:

export default function DashboardLayout({
children,
}: {
children: React.ReactNode
}) {
return <section>{children}</section>
}
export default function DashboardLayout({ children }) {
return <section>{children}</section>
}
إذا كنت ستجمع بين التخطيطين أعلاه، فإن التخطيط الجذري (app/layout.js
) سيغلف تخطيط لوحة التحكم (app/dashboard/layout.js
)، والذي بدوره سيغلف أجزاء المسار داخل app/dashboard/*
.
سيتم تداخل التخطيطين كما يلي:

جيد أن تعرف:
- يمكن استخدام امتدادات الملفات
.js
أو.jsx
أو.tsx
للتخطيطات.- فقط التخطيط الجذري يمكن أن يحتوي على علامات
<html>
و<body>
.- عند تعريف ملف
layout.js
وpage.js
في نفس المجلد، سيقوم التخطيط بتغليف الصفحة.- التخطيطات هي مكونات خادم (Server Components) افتراضيًا ولكن يمكن تعيينها كـ مكون عميل (Client Component).
- يمكن للتخطيطات جلب البيانات. راجع قسم جلب البيانات لمزيد من المعلومات.
- لا يمكن تمرير البيانات بين تخطيط رئيسي وأطفاله. ومع ذلك، يمكنك جلب نفس البيانات في مسار أكثر من مرة، وسيقوم React بإزالة التكرارات تلقائيًا دون التأثير على الأداء.
- لا يمكن للتخطيطات الوصول إلى أجزاء المسار أسفلها. للوصول إلى جميع أجزاء المسار، يمكنك استخدام
useSelectedLayoutSegment
أوuseSelectedLayoutSegments
في مكون عميل.- يمكنك استخدام مجموعات المسار (Route Groups) لاختيار أجزاء مسار محددة داخل أو خارج التخطيطات المشتركة.
- يمكنك استخدام مجموعات المسار (Route Groups) لإنشاء تخطيطات جذرية متعددة. راجع مثال هنا.
- الترحيل من دليل
pages
: يحل التخطيط الجذري محل ملفات_app.js
و_document.js
. راجع دليل الترحيل.
القوالب
القوالب مشابهة للتخطيطات من حيث أنها تغلف كل تخطيط فرعي أو صفحة. على عكس التخطيطات التي تستمر عبر المسارات وتحافظ على الحالة، تنشئ القوالب نسخة جديدة لكل من أطفالها عند التنقل. هذا يعني أنه عندما ينتقل المستخدم بين المسارات التي تشترك في قالب، يتم تحميل نسخة جديدة من المكون، يتم إعادة إنشاء عناصر DOM، لا يتم الحفاظ على الحالة، ويعاد مزامنة التأثيرات.
قد تكون هناك حالات تحتاج فيها إلى هذه السلوكيات المحددة، وتكون القوالب خيارًا أكثر ملاءمة من التخطيطات. على سبيل المثال:
- الميزات التي تعتمد على
useEffect
(مثل تسجيل مشاهدات الصفحة) وuseState
(مثل نموذج تعليقات لكل صفحة).
- لتغيير سلوك الإطار الافتراضي. على سبيل المثال، حدود Suspense داخل التخطيطات تظهر الحالة الاحتياطية فقط عند تحميل التخطيط لأول مرة وليس عند تبديل الصفحات. بالنسبة للقوالب، تظهر الحالة الاحتياطية في كل تنقل.
يمكن تعريف قالب عن طريق تصدير مكون React افتراضي من ملف template.js
. يجب أن يقبل المكون خاصية children
.

export default function Template({ children }: { children: React.ReactNode }) {
return <div>{children}</div>
}
export default function Template({ children }) {
return <div>{children}</div>
}
من حيث التداخل، يتم تصيير template.js
بين التخطيط وأطفاله. إليك نتيجة مبسطة:
<Layout>
{/* لاحظ أن القالب لديه مفتاح فريد. */}
<Template key={routeParam}>{children}</Template>
</Layout>
البيانات الوصفية
في دليل app
، يمكنك تعديل عناصر HTML <head>
مثل title
و meta
باستخدام واجهات برمجة تطبيقات البيانات الوصفية (Metadata APIs).
يمكن تعريف البيانات الوصفية عن طريق تصدير كائن metadata
أو دالة generateMetadata
في ملف layout.js
أو page.js
.
import { Metadata } from 'next'
export const metadata: Metadata = {
title: 'Next.js',
}
export default function Page() {
return '...'
}
export const metadata = {
title: 'Next.js',
}
export default function Page() {
return '...'
}
جيد أن تعرف: يجب ألا تضيف يدويًا علامات
<head>
مثل<title>
و<meta>
إلى التخطيطات الجذرية. بدلاً من ذلك، يجب استخدام واجهة برمجة تطبيقات البيانات الوصفية (Metadata API) التي تتعامل تلقائيًا مع المتطلبات المتقدمة مثل البث وإزالة تكرار عناصر<head>
.
تعرف على المزيد حول خيارات البيانات الوصفية المتاحة في مرجع API