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 ersetztslot
undslot-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 slot
Funktionen 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 Funktionenslot
undslot-scope
bereitzustellen.v-slot
Den vollständigen Ursprung finden Sie in diesem RFC. Die Funktionenslot
undslot-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-scope
Single 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>