Slot


Auf dieser Seite wird davon ausgegangen, dass Sie Komponentengrundlagen gelesen haben. Wenn Sie noch nicht viel über Komponenten wissen, empfehle ich Ihnen, es zuerst zu lesen.

In 2.6.0 haben wir eine neue einheitliche Syntax für benannte Slots und bereichsbezogene Slots eingeführt (die v-slot-Direktive). Es ersetzt slot und slot-scope , zwei derzeit veraltete, aber nicht entfernte Funktionen, die noch in der Dokumentation enthalten sind. Der Ursprung der neuen Syntax ist in diesem RFC zu finden.


Verzeichnis



Slot-Inhalte


Vue Eine Reihe von APIs zur Inhaltsverteilung wurde implementiert. Das Design dieser API ist vom Web Components-Spezifikationsentwurf inspiriert und verwendet das <slot>-Element als Ausgang für die Übertragung verteilter Inhalte.

Damit können Sie Komponenten wie folgt zusammenstellen:

<navigation-link url="/profile">
  Your Profile
</navigation-link>

Dann können Sie in die <navigation-link>-Vorlage schreiben:

<a
  v-bind:href="url"
  class="nav-link"
>
  <slot></slot>
</a>

Wenn die Komponente gerendert wird, wird <slot></slot> sein ersetzt durch „Ihr Profil“. Der Slot kann einen beliebigen Vorlagencode enthalten, einschließlich HTML:

<navigation-link url="/profile">
  <!-- 添加一个 Font Awesome 图标 -->
  <span class="fa fa-user"></span>
  Your Profile
</navigation-link>

oder sogar anderer Komponenten:

<navigation-link url="/profile">
  <!-- 添加一个图标的组件 -->
  <font-awesome-icon name="user"></font-awesome-icon>
  Your Profile
</navigation-link>

Wenn <navigation-link> kein <slot>-Element enthält, wird alles zwischen den Start- und End-Tags der Komponente verworfen.


Zusammenstellungsumfang


Wenn Sie möchten Bei der Verwendung von Daten in einem Slot, zum Beispiel:

<navigation-link url="/profile">
  Logged in as {{ user.name }}
</navigation-link>

Der Slot kann auf die gleichen Instanzeigenschaften zugreifen wie anderswo in der Vorlage. (d. h. derselbe „Bereich“), kann aber nicht auf den Bereich von <navigation-link> zugreifen. Beispielsweise ist die URL nicht zugänglich:

<navigation-link url="/profile">
  Clicking here will send you to: {{ url }}
  <!--
  这里的 `url` 会是 undefined,因为 "/profile" 是
  _传递给_ <navigation-link> 的而不是
  在 <navigation-link> 组件*内部*定义的。
  -->
</navigation-link>

Bedenken Sie in der Regel:

Alles in der übergeordneten Vorlage ist im übergeordneten Bereich. Alles in einem untergeordneten Element Die Vorlage wird im untergeordneten Bereich kompiliert.


Fallback-Inhalt


Manchmal für einen bestimmten Slot festgelegt Fallback (d. h. die Standardeinstellung) Inhalte sind nützlich und werden nur gerendert, wenn keine Inhalte bereitgestellt werden. Zum Beispiel in einer <submit-button>-Komponente:

<button type="submit">
  <slot></slot>
</button>

In den meisten Fällen möchten wir möglicherweise, dass dieses <button> den Text „Submit“ wiedergibt. Um „Senden“ als Fallback zu haben, können wir es in ein <slot>-Tag einfügen:

<button type="submit">
  <slot>Submit</slot>
</button>

Wenn ich jetzt <submit-button> in einer übergeordneten Komponente verwende Und wenn kein Slot-Inhalt bereitgestellt wird:

<submit-button></submit-button>

, wird der Fallback-Inhalt „Senden“ gerendert:

<button type="submit">
  Submit
</button>

Wenn wir jedoch Inhalte bereitstellen:

<submit-button>
  Save
</submit-button>

, dann dies Der bereitgestellte Inhalt wird gerendert und ersetzt den Fallback-Inhalt:

<button type="submit">
  Save
</button>


Benannte Slots


Aktualisiert seit 2.6.0. Die veraltete Syntax für die Verwendung des slot-Attributs finden Sie hier.

Manchmal benötigen wir mehrere Slots. Nehmen Sie zum Beispiel eine <base-layout>-Komponente mit der folgenden Vorlage:

<div class="container">
  <header>
    <!-- 我们希望把页头放这里 -->
  </header>
  <main>
    <!-- 我们希望把主要内容放这里 -->
  </main>
  <footer>
    <!-- 我们希望把页脚放这里 -->
  </footer>
</div>

Für solche Fälle hat das <slot>-Element ein spezielles Attribut: name. Mit dieser Funktion können zusätzliche Steckplätze definiert werden:

<div class="container">
  <header>
    <slot name="header"></slot>
  </header>
  <main>
    <slot></slot>
  </main>
  <footer>
    <slot name="footer"></slot>
  </footer>
</div>

Ein name-Ausgang ohne <slot> erhält den impliziten Namen „default“.

Bei der Bereitstellung von Inhalten für einen benannten Slot können wir die <template>-Direktive für ein v-slot-Element verwenden und dessen Namen als Argument für v-slot bereitstellen:

<base-layout>
  <template v-slot:header>
    <h1>Here might be a page title</h1>
  </template>
  <p>A paragraph for the main content.</p>
  <p>And another one.</p>
  <template v-slot:footer>
    <p>Here's some contact info</p>
  </template>
</base-layout>

Jetzt ist alles drin Das <template>-Element wird an den entsprechenden Slot übergeben. Alle Inhalte, die nicht in ein v-slot mit <template> eingeschlossen sind, werden als Inhalt des Standard-Slots behandelt.

Wenn Sie es jedoch expliziter machen möchten, können Sie den Inhalt des Standard-Slots trotzdem in ein <template> einschließen:

<base-layout>
  <template v-slot:header>
    <h1>Here might be a page title</h1>
  </template>
  <template v-slot:default>
    <p>A paragraph for the main content.</p>
    <p>And another one.</p>
  </template>
  <template v-slot:footer>
    <p>Here's some contact info</p>
  </template>
</base-layout>

In beiden Fällen wird Folgendes gerendert:

<div class="container">
  <header>
    <h1>Here might be a page title</h1>
  </header>
  <main>
    <p>A paragraph for the main content.</p>
    <p>And another one.</p>
  </main>
  <footer>
    <p>Here's some contact info</p>
  </footer>
</div>

Hinweis: v-slot kann nur zu einem <template> hinzugefügt werden (es gibt nur eine Ausnahme für ), was mit dem veralteten Element identisch ist slotFunktionen sind unterschiedlich.


Scope-Slots


Verfügbar seit 2.6.0 erneuern. Die veraltete Syntax für die Verwendung des slot-scope-Attributs finden Sie hier.

Manchmal ist es sinnvoll, dem Slot-Inhalt Zugriff auf Daten zu gewähren, die nur in der untergeordneten Komponente verfügbar sind. Stellen Sie sich zum Beispiel eine <current-user>-Komponente mit der folgenden Vorlage vor:

<span>
  <slot>{{ user.lastName }}</slot>
</span>

Wir möchten, dass ihr Fallback-Inhalt den Vornamen des Benutzers anstelle des Nachnamens des normalen Benutzers anzeigt, etwa so:

<current-user>
  {{ user.firstName }}
</current-user>

Der obige Code funktioniert jedoch nicht ordnungsgemäß, da nur die <current-user>-Komponente Zugriff auf user hat und der von uns bereitgestellte Inhalt auf der übergeordneten Ebene gerendert wird.

Um user im Inhalt des übergeordneten Slots verfügbar zu machen, können wir user als Attribut des <slot>-Elements binden:

<span>
  <slot v-bind:user="user">
    {{ user.lastName }}
  </slot>
</span>

ist an < Die Eigenschaften auf dem 🎜 gebunden >-Element heißen <slot>Slot-Requisiten. Jetzt können wir im übergeordneten Bereich einen Wert zuweisen, der den Namen der von uns bereitgestellten Slot-Requisite definiert: v-slot

<current-user>
  <template v-slot:default="slotProps">
    {{ slotProps.user.firstName }}
  </template>
</current-user>

In diesem Beispiel wählen wir das Objekt aus, das alle Slot-Requisiten enthalten soll. Benennen Sie es

, aber Sie können einen beliebigen Namen verwenden. slotProps


Abgekürzte Syntax für exklusiven Standard-Slot

Im oben genannten Fall, wenn der Inhalt nur bereitgestellt wird Im Standardsteckplatz kann die Beschriftung der Komponente als Vorlage für den Steckplatz verwendet werden. Auf diese Weise können wir

direkt auf der Komponente verwenden: v-slot

<current-user v-slot:default="slotProps">
  {{ slotProps.user.firstName }}
</current-user>

Diese Schreibweise kann einfacher sein. So wie davon ausgegangen wird, dass nicht spezifizierter Inhalt dem Standard-Slot entspricht, wird davon ausgegangen, dass

ohne Argument dem Standard-Slot entspricht: v-slot

<current-user v-slot="slotProps">
  {{ slotProps.user.firstName }}
</current-user>

Beachten Sie, dass die Abkürzungssyntax für den Standard-Slot

nicht < sein kann 🎜> und „Mischen von Slots“ genannt, da dies zu Mehrdeutigkeit des Umfangs führt:

<!-- 无效,会导致警告 -->
<current-user v-slot="slotProps">
  {{ slotProps.user.firstName }}
  <template v-slot:other="otherSlotProps">
    slotProps is NOT available here
  </template>
</current-user>
Wenn mehrere Slots vorhanden sind, verwenden Sie immer die Vollständigkeit Syntax für

:

<current-user>
  <template v-slot:default="slotProps">
    {{ slotProps.user.firstName }}
  </template>
  <template v-slot:other="otherSlotProps">
    ...
  </template>
</current-user>
<template>


Destructuring Slot Prop Internals of Scoped Slot So funktioniert das Dies geschieht, indem Sie den Inhalt Ihres Slots in eine Funktion einschließen, die ein einzelnes Argument akzeptiert:

function (slotProps) {
  // 插槽内容
}

Das bedeutet, dass der Wert von v-slot tatsächlich jeder JavaScript-Ausdruck sein kann, der als Parameter in einer Funktionsdefinition übergeben werden kann. In einer unterstützten Umgebung (Single File Component oder Modern Browser) können Sie also auch ES2015 Destrukturierung verwenden, um bestimmte Slot-Requisiten wie folgt zu übergeben:

<current-user v-slot="{ user }">
  {{ user.firstName }}
</current-user>

Dies kann die Vorlage prägnanter machen, insbesondere wenn der Slot mehrere Requisiten bereitstellt. Es eröffnet auch andere Möglichkeiten für die Umbenennung von Requisiten, z. B. die Umbenennung von user in person:

<current-user v-slot="{ user: person }">
  {{ person.firstName }}
</current-user>

. Sie können sogar Fallback-Inhalte für nicht definierte Slot-Requisiten definieren Situation:

<current-user v-slot="{ user = { firstName: 'Guest' } }">
  {{ user.firstName }}
</current-user>


Dynamischer Slot-Name


2.6.0 Neu hinzugefügt

Dynamische Befehlsparameter können auch in verwendet werden v-slot So definieren Sie dynamische Slot-Namen:

<base-layout>
  <template v-slot:[dynamicSlotName]>
    ...
  </template>
</base-layout>


named Slot-Abkürzung


2.6.0 hinzugefügt

und v-on Wie v-bind verfügt auch v-slot über eine Abkürzung, die alles vor dem Parameter (v-slot:) durch die Zeichen # ersetzt. Beispielsweise kann v-slot:header als #header umgeschrieben werden:

<base-layout>
  <template #header>
    <h1>Here might be a page title</h1>
  </template>
  <p>A paragraph for the main content.</p>
  <p>And another one.</p>
  <template #footer>
    <p>Here's some contact info</p>
  </template>
</base-layout>

Allerdings ist diese Abkürzung wie andere Anweisungen nur verfügbar, wenn sie Argumente enthält. Dies bedeutet, dass die folgende Syntax ungültig ist:

<!-- 这样会触发一个警告 -->
<current-user #="{ user }">
  {{ user.firstName }}
</current-user>

Wenn Sie die Abkürzung verwenden möchten, müssen Sie diese immer durch den expliziten Slotnamen ersetzen :

<current-user #default="{ user }">
  {{ user.firstName }}
</current-user>


Andere Beispiele


Slot Mithilfe von Requisiten können wir Slots in wiederverwendbare Vorlagen umwandeln, die basierend auf den Eingabe-Requisiten unterschiedliche Inhalte rendern können. Dies ist am nützlichsten, wenn Sie wiederverwendbare Komponenten entwerfen, die die Datenlogik kapseln und gleichzeitig der übergeordneten Komponente ermöglichen, einen Teil des Layouts anzupassen.

Zum Beispiel möchten wir eine <todo-list>-Komponente implementieren, die eine Liste ist und Layout- und Filterlogik enthält:

<ul>
  <li
    v-for="todo in filteredTodos"
    v-bind:key="todo.id"
  >
    {{ todo.text }}
  </li>
</ul>

Wir können jede Aufgabe als Slot der übergeordneten Komponente verwenden Dies steuert es über die übergeordnete Komponente und bindet dann todo als Slot-Requisite:

<ul>
  <li
    v-for="todo in filteredTodos"
    v-bind:key="todo.id"
  >
    <!--
    我们为每个 todo 准备了一个插槽,
    将 `todo` 对象作为一个插槽的 prop 传入。
    -->
    <slot name="todo" v-bind:todo="todo">
      <!-- 后备内容 -->
      {{ todo.text }}
    </slot>
  </li>
</ul>

Jetzt verwenden wir <todo-list>-Komponente können wir alternativ ein anderes <template> für todo definieren und Daten von der untergeordneten Komponente abrufen:

<todo-list v-bind:todos="todos">
  <template v-slot:todo="{ todo }">
    <span v-if="todo.isComplete">?</span>
    {{ todo.text }}
  </template>
</todo-list>

Das ist nur die Spitze des Eisbergs dessen, was Scope-Slots leisten können. Für eine realistischere Nutzung von Slots mit Gültigkeitsbereich empfehlen wir das Durchsuchen von Bibliotheken wie Vue Virtual Scroller, Vue Promised und Portal Vue.


Veraltete Syntax


v-slot In Vue 2.6.0 wurden Direktiven eingeführt, um eine API-Alternative mit besserer Unterstützung für die Funktionen slot und slot-scope bereitzustellen. v-slot Den vollständigen Ursprung finden Sie in diesem RFC. Die Funktionen slot und slot-scope werden in allen nachfolgenden 2.x-Versionen weiterhin unterstützt, sind jedoch offiziell veraltet und werden in Vue 3 nicht angezeigt.


Benannter Slot mit der Eigenschaft slot

Seit 2.6.0 veraltet. Die neue empfohlene Syntax finden Sie hier.

Verwenden Sie das spezielle <template>-Attribut für slot, um Inhalte vom übergeordneten Element an den benannten Slot zu übergeben (setzen Sie wie erwähnt hier<base-layout> als Komponente ein). Beispiel):

<base-layout>
  <template slot="header">
    <h1>Here might be a page title</h1>
  </template>
  
  <p>A paragraph for the main content.</p>
  <p>And another one.</p>
  
  <template slot="footer">
    <p>Here's some contact info</p>
  </template>
</base-layout>

oder geben Sie einfach slot ein Das Attribut wird für ein gewöhnliches Element verwendet:

<base-layout>
  <h1 slot="header">Here might be a page title</h1>
  
  <p>A paragraph for the main content.</p>
  <p>And another one.</p>
  
  <p slot="footer">Here's some contact info</p>
</base-layout>

Hier gibt es tatsächlich einen unbenannten Slot, nämlich den Standardslot, der alle nicht übereinstimmenden Inhalte erfasst. Die HTML-Rendering-Ergebnisse der beiden oben genannten Beispiele sind:

<div class="container">
  <header>
    <h1>Here might be a page title</h1>
  </header>
  <main>
    <p>A paragraph for the main content.</p>
    <p>And another one.</p>
  </main>
  <footer>
    <p>Here's some contact info</p>
  </footer>
</div>


Scope-Slot mit slot-scope-Attribut

Veraltet seit 2.6.0. Die neue empfohlene Syntax finden Sie hier.

Verwenden Sie das spezielle <template>-Attribut auf slot-scope, um die an den Slot übergebene Requisite zu erhalten (nehmen Sie die hier erwähnte -Komponente als Beispiel):<slot-example>

<slot-example>
  <template slot="default" slot-scope="slotProps">
    {{ slotProps.msg }}
  </template>
</slot-example>

Das slot-scope hier deklariert, dass das empfangene Requisitenobjekt im slotProps-Bereich als <template>-Variable vorhanden sein wird. Sie können slotProps alles benennen, was Sie möchten, so wie Sie JavaScript-Funktionsparameter benennen.

Das slot="default" hier kann als implizites Schreiben ignoriert werden:

<slot-example>
  <template slot-scope="slotProps">
    {{ slotProps.msg }}
  </template>
</slot-example>

slot-scope Das Attribut kann auch direkt auf Nicht-<template>-Elementen (einschließlich Komponenten) verwendet werden:

<slot-example>
  <span slot-scope="slotProps">
    {{ slotProps.msg }}
  </span>
</slot-example>
< Der Wert von 🎜>

kann jeden gültigen JavaScript-Ausdruck akzeptieren, der an der Parameterposition der Funktionsdefinition erscheinen kann. Das bedeutet, dass Sie in unterstützten Umgebungen (slot-scopeSingle File Components oder Modern Browsers) auch Destrukturierung ES2015 in einem Ausdruck verwenden können, wie folgt:

<slot-example>
  <span slot-scope="{ msg }">
    {{ msg }}
  </span>
</slot-example>

verwendet

wie hier beschrieben Der entsprechende Code, der <todo-list> verwendet, lautet beispielsweise: slot-scope

<todo-list v-bind:todos="todos">
  <template slot="todo" slot-scope="{ todo }">
    <span v-if="todo.isComplete">?</span>
    {{ todo.text }}
  </template>
</todo-list>