كيفية إنشاء التخطيطات والصفحات

يستخدم Next.js التوجيه القائم على نظام الملفات، مما يعني أنه يمكنك استخدام المجلدات والملفات لتحديد المسارات. سيرشدك هذه الصفحة حول كيفية إنشاء التخطيطات والصفحات، والربط بينها.

إنشاء صفحة

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

ملف page.js الخاص
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:

ملف layout.js الخاص
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:

تسلسل الملفات يظهر مجلد blog وملف page.js
// استيرادات وهمية
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:

تسلسل الملفات يظهر مجلد blog مع مجلد slug متداخل وملف page.js
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 للتنقل المتقدم.