Machen Sie sich mit Vue.js Scoped Slots vertraut

Scoped Slots sind ein nützliches Feature von Vue.js, das Komponenten vielseitiger und wiederverwendbar machen kann. Das einzige Problem ist, dass sie schwer zu verstehen sind! Der Versuch, sich mit der Verflechtung von übergeordneten und untergeordneten Bereichen vertraut zu machen, ist wie das Lösen einer schwierigen mathematischen Gleichung.

Ein guter Ansatz, wenn Sie etwas nicht leicht verstehen können, besteht darin, zu versuchen, es bei der Lösung eines Problems anzuwenden. In diesem Artikel zeige ich, wie ich bereichsbezogene Slots verwendet habe, um eine wiederverwendbare Listenkomponente zu erstellen.

scoped_slots_02.png

Hinweis: Sie können das fertige Produkt in sehen dieser Codestift.

Hinweis: Dieser Artikel wurde ursprünglich veröffentlicht hier im Vue.js-Entwicklerblog am 02.10.2017.

Die Grundkomponente

Die Komponente, die wir bauen werden, heißt my-list und es zeigt Listen von Dingen an. Das Besondere ist, dass Sie bei jeder Verwendung der Komponente anpassen können, wie die Listenelemente gerendert werden.

Lassen Sie uns zuerst den einfachsten Anwendungsfall angehen und erhalten my-list um nur eine Liste von Dingen zu rendern: eine Reihe geometrischer Formnamen und die Anzahl der Seiten, die sie haben.

app.js

Vue.component('my-list', {
  template: '#my-list',
  data() {
    return {
      title: 'Shapes',
      shapes: [ 
        { name: 'Square', sides: 4 }, 
        { name: 'Hexagon', sides: 6 }, 
        { name: 'Triangle', sides: 3 }
      ]
    };
  }
});

new Vue({
  el: '#app'
});

index.html

<div id="app">
  <my-list></my-list>
</div>

<script type="text/x-template" id="my-list">
  <div class="my-list">
    <div class="title">{{ title }}</div>
    <div class="list">
      <div class="list-item" v-for="shape in shapes">
        <div>{{ shape.name }} <small>({{ shape.sides }} sides)</small></div>
      </div>
    </div>
  </div>
</script>

Mit etwas CSS sieht das so aus:

scoped_slots_01.png

Verallgemeinern my-list

Jetzt wollen wir machen my-list vielseitig genug, um jede Art von Liste zu rendern. Der zweite Testfall ist eine Liste von Farben, einschließlich eines kleinen Musters, um zu zeigen, wie die Farbe aussieht.

Dazu müssen wir alle für die Formenliste spezifischen Daten abstrahieren. Da die Artikel in unseren Listen unterschiedlich aufgebaut sein können, geben wir nach my-list ein Slot, damit der Elternteil definieren kann, wie eine bestimmte Liste angezeigt wird.

app.js

Vue.component('my-list', {
  template: '#my-list',
  props: [ 'title' ]
});

index.html

<script type="text/x-template" id="my-list">
  <div class="my-list">
    <div class="title">{{ title }}</div>
    <div class="list">
      <slot></slot>
    </div>
  </div>
</script>

Lassen Sie uns nun zwei Instanzen von erstellen my-list Komponente in der Root-Instanz, um unsere beiden Testfalllisten anzuzeigen:

app.js

new Vue({
  el: '#app',
  data: {
    shapes: [ 
      { name: 'Square', sides: 4 }, 
      { name: 'Hexagon', sides: 6 }, 
      { name: 'Triangle', sides: 3 }
    ],
    colors: [
      { name: 'Yellow', hex: '#F4D03F', },
      { name: 'Green', hex: '#229954' },
      { name: 'Purple', hex: '#9B59B6' }
    ]
  }
});
<div id="app">
  <my-list :title="Shapes">
    <div class="list-item" v-for="item in shapes">
      <div>{{ shape.name }} <small>({{ shape.sides }} sides)</small></div>
    </div>
  </my-list>
  <my-list :title="Colors">
    <div class="list-item" v-for="color in colors">
      <div>
        <div class="swatch" :style="{ background: color.hex }"></div>
        {{ color.name }}
      </div>
    </div>
  </my-list>
</div>

Das wird so aussehen:

Form- und Farbliste

Oberflächliche Komponenten

Was wir gerade erstellt haben, funktioniert gut, ist aber kein großartiger Code. my-list ist dem Namen nach eine Komponente zum Anzeigen einer Liste. Aber wir mussten die gesamte Logik zum Rendern der Liste in die Elterndatei abstrahieren. Die Komponente macht kaum mehr, als die Liste mit etwas Präsentations-Markup zu umhüllen.

Da es in beiden Deklarationen der Komponente immer noch wiederholten Code gibt (dh <div class="list-item" v-for="item in ...">), wäre es toll, wenn wir das an die Komponente delegieren könnten, damit es nicht so oberflächlich ist.

Slots mit Zielfernrohr

Um dies zu ermöglichen, verwenden wir a Scope-Steckplatz anstelle eines regulären Steckplatzes. Slots mit Zielfernrohr ermöglichen es Ihnen, a Schablone an den Schlitz, anstatt ein gerendertes Element zu übergeben. Es wird als “bereichsbezogener” Slot bezeichnet, da die Vorlage zwar im übergeordneten Bereich gerendert wird, aber Zugriff auf bestimmte untergeordnete Daten hat.

Zum Beispiel eine Komponente child mit einem Bereichssteckplatz könnte wie folgt aussehen.

<div>
  <slot my-prop="Hello from child"></slot>
</div>

Ein Elternteil, der diese Komponente verwendet, deklariert a template Element im Steckplatz. Dieses Vorlagenelement hat ein Attribut scope das ein Alias-Objekt benennt. Alle Requisiten, die dem Slot (in der Vorlage des Kindes) hinzugefügt wurden, sind als Eigenschaften des Alias-Objekts verfügbar.

<child>
  <template scope="props">
    <span>Hello from parent</span>
    <span>{{ props.my-prop }}</span>
  </template>
</child>

Rendert als:

<div>
  <span>Hello from parent</span>
  <span>Hello from child</span>
</div>

Verwenden eines Scoped-Slots in my-list

Übergeben wir die Listen-Arrays an my-list als Requisiten. Dann können wir den Slot durch einen Scoped Slot ersetzen. Dieser Weg my-list kann für das Iterieren der Listenelemente verantwortlich sein, aber das übergeordnete Element kann weiterhin definieren, wie jedes Listenelement angezeigt werden soll.

index.html

<div id="app">
  <my-list title="Shapes" :items="shapes">
    
  </my-list>
  <my-list title="Colors" :items="colors">
    
  </my-list>   
</div>

Jetzt bekommen wir my-list um die Elemente zu iterieren. Im Inneren des v-for Schleife, item ist ein Alias ​​für das aktuelle Listenelement. Wir können einen Slot erstellen und dieses Listenelement mithilfe von an den Slot binden v-bind="item".

app.js

Vue.component('my-list', {
  template: '#my-list',
  props: [ 'title', 'items' ]
});

index.html

<script type="text/x-template" id="my-list">
  <div class="my-list">
    <div class="title">{{ title }}</div>
    <div class="list">
      <div v-for="item in items">
        <slot v-bind="item"></slot>
      </div>
    </div>
  </div>
</script>

Hinweis: Wenn Sie es nicht gesehen haben v-bind zuvor ohne Argument verwendet, bindet dies die Eigenschaften eines gesamten Objekts an das Element. Dies ist bei bereichsbezogenen Slots nützlich, da die Objekte, die Sie binden, häufig willkürliche Eigenschaften haben, die jetzt nicht mehr namentlich angegeben werden müssen.

Jetzt kehren wir zu unserer Root-Instanz zurück und deklarieren eine Vorlage im Slot von my-list. Wenn Sie sich zuerst die Formenliste ansehen, muss die Vorlage die enthalten scope Eigenschaft, der wir einen Alias ​​zuweisen shape. Dieser Alias ​​ermöglicht uns den Zugriff auf die Scoped Props. Innerhalb der Vorlage können wir genau das gleiche Markup verwenden, das wir zuvor hatten, um unsere Formlistenelemente anzuzeigen.

<my-list title="Shapes" :items="shapes">
  <template scope="shape">
    <div>{{ shape.name }} <small>({{ shape.sides }} sides)</small></div>
  </template>
</my-list>

Hier ist nun die vollständige Vorlage:

<div id="app">
  <my-list title="Shapes" :items="shapes">
    <template scope="shape">
      <div>{{ shape.name }} <small>({{ shape.sides }} sides)</small></div>
    </template>
  </my-list>
  <my-list title="Colors" :items="colors">
    <template scope="color">
      <div>
        <div class="swatch" :style="{ background: color.hex }"></div>
        {{ color.name }}
      </div>
    </template>
  </my-list>   
</div>

Fazit

Obwohl dieser Ansatz genauso viel Markup wie zuvor hat, hat er die gemeinsame Funktionalität an die Komponente delegiert, was für ein robusteres Design sorgt.


Werden Sie 2020 Senior Vue-Entwickler.

Lernen und beherrschen Sie in unserem neuesten Kurs, was Profis über das Erstellen, Testen und Bereitstellen von Full-Stack-Vue-Apps wissen.

Mehr erfahren


Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *