Seiten und Layouts

Wir empfehlen, die Seiten Routing-Grundlagen und Routen definieren zu lesen, bevor Sie fortfahren.

Die speziellen Dateien layout.js, page.js und template.js ermöglichen es Ihnen, Benutzeroberflächen für eine Route zu erstellen. Diese Seite führt Sie durch die Verwendung dieser speziellen Dateien.

Seiten

Eine Seite ist eine Benutzeroberfläche, die für eine Route eindeutig ist. Sie können eine Seite definieren, indem Sie eine Komponente standardmäßig aus einer page.js-Datei exportieren.

Um beispielsweise Ihre index-Seite zu erstellen, fügen Sie die page.js-Datei im app-Verzeichnis hinzu:

page.js special file
// `app/page.tsx` ist die Benutzeroberfläche für die URL `/`
export default function Page() {
  return <h1>Hallo, Startseite!</h1>
}
// `app/page.js` ist die Benutzeroberfläche für die URL `/`
export default function Page() {
  return <h1>Hallo, Startseite!</h1>
}

Um weitere Seiten zu erstellen, erstellen Sie einen neuen Ordner und fügen Sie die page.js-Datei darin hinzu. Um beispielsweise eine Seite für die Route /dashboard zu erstellen, erstellen Sie einen neuen Ordner namens dashboard und fügen Sie die page.js-Datei darin hinzu:

// `app/dashboard/page.tsx` ist die Benutzeroberfläche für die URL `/dashboard`
export default function Page() {
  return <h1>Hallo, Dashboard-Seite!</h1>
}
// `app/dashboard/page.js` ist die Benutzeroberfläche für die URL `/dashboard`
export default function Page() {
  return <h1>Hallo, Dashboard-Seite!</h1>
}

Wissenswert:

  • Die Dateierweiterungen .js, .jsx oder .tsx können für Seiten verwendet werden.
  • Eine Seite ist immer das Blatt des Route-Unterbaums.
  • Eine page.js-Datei ist erforderlich, um ein Routensegment öffentlich zugänglich zu machen.
  • Seiten sind standardmäßig Server Components, können aber als Client Component festgelegt werden.
  • Seiten können Daten abrufen. Weitere Informationen finden Sie im Abschnitt Datenabruf.

Layouts

Ein Layout ist eine Benutzeroberfläche, die zwischen mehreren Routen geteilt wird. Bei der Navigation behalten Layouts den Zustand bei, bleiben interaktiv und werden nicht neu gerendert. Layouts können auch verschachtelt werden.

Sie können ein Layout definieren, indem Sie eine React-Komponente standardmäßig aus einer layout.js-Datei exportieren. Die Komponente sollte eine children-Prop akzeptieren, die während des Renderings mit einem untergeordneten Layout (falls vorhanden) oder einer Seite gefüllt wird.

Beispielsweise wird das Layout mit den Seiten /dashboard und /dashboard/settings geteilt:

layout.js special file
export default function DashboardLayout({
  children, // wird eine Seite oder ein verschachteltes Layout sein
}: {
  children: React.ReactNode
}) {
  return (
    <section>
      {/* Gemeinsame Benutzeroberfläche hier einfügen, z.B. eine Kopfzeile oder Seitenleiste */}
      <nav></nav>

      {children}
    </section>
  )
}
export default function DashboardLayout({
  children, // wird eine Seite oder ein verschachteltes Layout sein
}) {
  return (
    <section>
      {/* Gemeinsame Benutzeroberfläche hier einfügen, z.B. eine Kopfzeile oder Seitenleiste */}
      <nav></nav>

      {children}
    </section>
  )
}

Root Layout (Erforderlich)

Das Root-Layout wird auf der obersten Ebene des app-Verzeichnisses definiert und gilt für alle Routen. Dieses Layout ist erforderlich und muss html- und body-Tags enthalten, damit Sie das anfängliche HTML, das vom Server zurückgegeben wird, ändern können.

export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html lang="en">
      <body>
        {/* Layout-Benutzeroberfläche */}
        <main>{children}</main>
      </body>
    </html>
  )
}
export default function RootLayout({ children }) {
  return (
    <html lang="en">
      <body>
        {/* Layout-Benutzeroberfläche */}
        <main>{children}</main>
      </body>
    </html>
  )
}

Verschachtelte Layouts

Standardmäßig sind Layouts in der Ordnerhierarchie verschachtelt, was bedeutet, dass sie untergeordnete Layouts über ihre children-Prop umschließen. Sie können Layouts verschachteln, indem Sie layout.js in bestimmten Routensegmenten (Ordnern) hinzufügen.

Um beispielsweise ein Layout für die Route /dashboard zu erstellen, fügen Sie eine neue layout.js-Datei im dashboard-Ordner hinzu:

Nested Layout
export default function DashboardLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return <section>{children}</section>
}
export default function DashboardLayout({ children }) {
  return <section>{children}</section>
}

Wenn Sie die beiden oben genannten Layouts kombinieren würden, würde das Root-Layout (app/layout.js) das Dashboard-Layout (app/dashboard/layout.js) umschließen, das wiederum die Routensegmente in app/dashboard/* umschließen würde.

Die beiden Layouts würden wie folgt verschachtelt sein:

Nested Layouts

Wissenswert:

  • Die Dateierweiterungen .js, .jsx oder .tsx können für Layouts verwendet werden.
  • Nur das Root-Layout kann <html>- und <body>-Tags enthalten.
  • Wenn eine layout.js- und eine page.js-Datei im selben Ordner definiert sind, wird das Layout die Seite umschließen.
  • Layouts sind standardmäßig Server Components, können aber als Client Component festgelegt werden.
  • Layouts können Daten abrufen. Weitere Informationen finden Sie im Abschnitt Datenabruf.
  • Die Weitergabe von Daten zwischen einem übergeordneten Layout und seinen untergeordneten Elementen ist nicht möglich. Sie können jedoch dieselben Daten in einer Route mehrmals abrufen, und React wird die Anfragen automatisch deduplizieren, ohne die Leistung zu beeinträchtigen.
  • Layouts haben keinen Zugriff auf die darunter liegenden Routensegmente. Um auf alle Routensegmente zuzugreifen, können Sie useSelectedLayoutSegment oder useSelectedLayoutSegments in einer Client-Komponente verwenden.
  • Sie können Route Groups verwenden, um bestimmte Routensegmente in gemeinsame Layouts einzubeziehen oder auszuschließen.
  • Sie können Route Groups verwenden, um mehrere Root-Layouts zu erstellen. Siehe ein Beispiel hier.
  • Migration vom pages-Verzeichnis: Das Root-Layout ersetzt die Dateien _app.js und _document.js. Siehe Migrationsleitfaden.

Templates

Templates ähneln Layouts darin, dass sie jedes untergeordnete Layout oder jede Seite umschließen. Im Gegensatz zu Layouts, die über Routen hinweg bestehen bleiben und den Zustand beibehalten, erstellen Templates für jedes ihrer untergeordneten Elemente eine neue Instanz bei der Navigation. Das bedeutet, dass beim Navigieren zwischen Routen, die ein Template teilen, eine neue Instanz der Komponente eingebunden wird, DOM-Elemente neu erstellt werden, der Zustand nicht erhalten bleibt und Effekte neu synchronisiert werden.

Es gibt Fälle, in denen Sie dieses spezifische Verhalten benötigen, und Templates wären eine geeignetere Option als Layouts. Zum Beispiel:

  • Funktionen, die auf useEffect basieren (z.B. Protokollierung von Seitenaufrufen) und useState (z.B. ein Feedback-Formular pro Seite).
  • Um das Standardverhalten des Frameworks zu ändern. Beispielsweise zeigen Suspense Boundaries in Layouts den Fallback nur beim ersten Laden des Layouts und nicht beim Wechseln der Seiten an. Bei Templates wird der Fallback bei jeder Navigation angezeigt.

Ein Template kann definiert werden, indem eine React-Komponente standardmäßig aus einer template.js-Datei exportiert wird. Die Komponente sollte eine children-Prop akzeptieren.

template.js special file
export default function Template({ children }: { children: React.ReactNode }) {
  return <div>{children}</div>
}
export default function Template({ children }) {
  return <div>{children}</div>
}

In Bezug auf die Verschachtelung wird template.js zwischen einem Layout und seinen untergeordneten Elementen gerendert. Hier ist eine vereinfachte Ausgabe:

Output
<Layout>
  {/* Beachten Sie, dass das Template einen eindeutigen Schlüssel erhält. */}
  <Template key={routeParam}>{children}</Template>
</Layout>

Metadaten

Im app-Verzeichnis können Sie HTML-Elemente wie title und meta im <head> mit den Metadaten-APIs ändern.

Metadaten können definiert werden, indem ein metadata-Objekt oder eine generateMetadata-Funktion in einer layout.js- oder page.js-Datei exportiert wird.

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 '...'
}

Wissenswert: Sie sollten <head>-Tags wie <title> und <meta> nicht manuell zu Root-Layouts hinzufügen. Verwenden Sie stattdessen die Metadaten-API, die erweiterte Anforderungen wie Streaming und Deduplizierung von <head>-Elementen automatisch handhabt.

Erfahren Sie mehr über verfügbare Metadatenoptionen in der API-Referenz