كيفية إنشاء التخطيطات والصفحات
يستخدم Next.js التوجيه القائم على نظام الملفات، مما يعني أنه يمكنك استخدام المجلدات والملفات لتحديد المسارات. سيرشدك هذه الصفحة حول كيفية إنشاء التخطيطات والصفحات، والربط بينها.
إنشاء صفحة
الصفحة هي واجهة مستخدم يتم عرضها على مسار معين. لإنشاء صفحة، أضف ملف page
داخل دليل app
وقم بتصدير مكون React افتراضيًا. على سبيل المثال، لإنشاء صفحة رئيسية (/
):

export default function Page() {
return <h1>Hello Next.js!</h1>
}
export default function Page() {
return <h1>Hello Next.js!</h1>
}
إنشاء تخطيط
التخطيط هو واجهة مستخدم مشتركة بين عدة صفحات. عند التنقل، تحافظ التخطيطات على الحالة، تبقى تفاعلية، ولا يتم إعادة عرضها.
يمكنك تحديد تخطيط عن طريق تصدير مكون React افتراضيًا من ملف layout
. يجب أن يقبل المكون خاصية children
والتي يمكن أن تكون صفحة أو تخطيط آخر.
على سبيل المثال، لإنشاء تخطيط يقبل صفحتك الرئيسية كطفل، أضف ملف layout
داخل دليل app
:

export default function DashboardLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<html lang="en">
<body>
{/* واجهة التخطيط */}
{/* ضع children حيث تريد عرض صفحة أو تخطيط متداخل */}
<main>{children}</main>
</body>
</html>
)
}
export default function DashboardLayout({ children }) {
return (
<html lang="en">
<body>
{/* واجهة التخطيط */}
{/* ضع children حيث تريد عرض صفحة أو تخطيط متداخل */}
<main>{children}</main>
</body>
</html>
)
}
يسمى التخطيط أعلاه تخطيط الجذر لأنه محدد في جذر دليل app
. تخطيط الجذر مطلوب ويجب أن يحتوي على علامات html
و body
.
إنشاء مسار متداخل
المسار المتداخل هو مسار يتكون من عدة أجزاء URL. على سبيل المثال، يتكون مسار /blog/[slug]
من ثلاثة أجزاء:
/
(جزء الجذر)blog
(جزء)[slug]
(جزء ورقي)
في Next.js:
- المجلدات تستخدم لتحديد أجزاء المسار التي تعين إلى أجزاء URL.
- الملفات (مثل
page
وlayout
) تستخدم لإنشاء واجهة مستخدم تعرض لجزء.
لإنشاء مسارات متداخلة، يمكنك تداخل المجلدات داخل بعضها البعض. على سبيل المثال، لإضافة مسار لـ /blog
، أنشئ مجلدًا يسمى blog
في دليل app
. ثم، لجعل /blog
متاحًا للجمهور، أضف ملف page.tsx
:

// استيرادات وهمية
import { getPosts } from '@/lib/posts'
import { Post } from '@/ui/post'
export default async function Page() {
const posts = await getPosts()
return (
<ul>
{posts.map((post) => (
<Post key={post.id} post={post} />
))}
</ul>
)
}
// استيرادات وهمية
import { getPosts } from '@/lib/posts'
import { Post } from '@/ui/post'
export default async function Page() {
const posts = await getPosts()
return (
<ul>
{posts.map((post) => (
<Post key={post.id} post={post} />
))}
</ul>
)
}
يمكنك مواصلة تداخل المجلدات لإنشاء مسارات متداخلة. على سبيل المثال، لإنشاء مسار لمنشور مدونة معين، أنشئ مجلد [slug]
جديد داخل blog
وأضف ملف page
:

function generateStaticParams() {}
export default function Page() {
return <h1>Hello, Blog Post Page!</h1>
}
function generateStaticParams() {}
export default function Page() {
return <h1>Hello, Blog Post Page!</h1>
}
لف اسم المجلد بين أقواس مربعة (مثل [slug]
) ينشئ جزء مسار ديناميكي يستخدم لإنشاء صفحات متعددة من البيانات. مثل منشورات المدونة، صفحات المنتجات، إلخ.
تداخل التخطيطات
افتراضيًا، التخطيطات في تسلسل المجلدات متداخلة أيضًا، مما يعني أنها تغلف التخطيطات الفرعية عبر خاصية children
. يمكنك تداخل التخطيطات عن طريق إضافة layout
داخل أجزاء مسار معينة (مجلدات).
على سبيل المثال، لإنشاء تخطيط لمسار /blog
، أضف ملف layout
جديد داخل مجلد blog
.

export default function BlogLayout({
children,
}: {
children: React.ReactNode
}) {
return <section>{children}</section>
}
export default function BlogLayout({ children }) {
return <section>{children}</section>
}
إذا قمت بدمج التخطيطين أعلاه، فإن تخطيط الجذر (app/layout.js
) سيغلف تخطيط المدونة (app/blog/layout.js
)، والذي بدوره سيغلف صفحة المدونة (app/blog/page.js
) وصفحة منشور المدونة (app/blog/[slug]/page.js
).
إنشاء جزء ديناميكي
الأجزاء الديناميكية تتيح لك إنشاء مسارات يتم إنشاؤها من البيانات. على سبيل المثال، بدلاً من إنشاء مسار يدويًا لكل منشور مدونة فردي، يمكنك إنشاء جزء ديناميكي لإنشاء المسارات بناءً على بيانات منشور المدونة.
لإنشاء جزء ديناميكي، لف اسم الجزء (المجلد) بين أقواس مربعة: [segmentName]
. على سبيل المثال، في مسار app/blog/[slug]/page.tsx
، [slug]
هو الجزء الديناميكي.
export default async function BlogPostPage({
params,
}: {
params: Promise<{ slug: string }>
}) {
const { slug } = await params
const post = await getPost(slug)
return (
<div>
<h1>{post.title}</h1>
<p>{post.content}</p>
</div>
)
}
export default async function BlogPostPage({ params }) {
const { slug } = await params
const post = await getPost(slug)
return (
<div>
<h1>{post.title}</h1>
<p>{post.content}</p>
</div>
)
}
تعلم المزيد عن الأجزاء الديناميكية.
الربط بين الصفحات
يمكنك استخدام مكون <Link>
للتنقل بين المسارات. <Link>
هو مكون مضمن في Next.js يمتد علامة HTML <a>
لتوفير الجلب المسبق والتنقل من جانب العميل.
على سبيل المثال، لإنشاء قائمة بمنشورات المدونة، استورد <Link>
من next/link
ومرر خاصية href
إلى المكون:
import Link from 'next/link'
export default async function Post({ post }) {
const posts = await getPosts()
return (
<ul>
{posts.map((post) => (
<li key={post.slug}>
<Link href={`/blog/${post.slug}`}>{post.title}</Link>
</li>
))}
</ul>
)
}
import Link from 'next/link'
export default async function Post({ post }) {
const posts = await getPosts()
return (
<ul>
{posts.map((post) => (
<li key={post.slug}>
<Link href={`/blog/${post.slug}`}>{post.title}</Link>
</li>
))}
</ul>
)
}
جيد أن تعرف:
<Link>
هو الطريقة الأساسية للتنقل بين المسارات في Next.js. يمكنك أيضًا استخدام خطافuseRouter
للتنقل المتقدم.