Eine kurze Diskussion zum Implementierungsprinzip des Vue-Slots

Eine kurze Diskussion zum Implementierungsprinzip des Vue-Slots

1. Beispielcode

<!-- Unterkomponente comA -->
<Vorlage>
  <div Klasse='Demo'>
    <Steckplatz><Steckplatz>
    <slotname='test'></slot>
    <slot name='scopedSlots' test='demo'></slot>
  </div>
</Vorlage>
<!-- Übergeordnete Komponente -->
<comA>
  <span>Dies ist der Standardsteckplatz</span>
  <template slot='test'>Dies ist ein benannter Slot</template>
  <template slot='scopedSlots' slot-scope='scope'>Dies ist ein Scoped Slot (alte Version) {{scope.test}}</template>
  <template v-slot:scopedSlots='scopeProps' slot-scope='scope'>Dies ist ein Scoped Slot (neue Version) {{scopeProps.test}}</template>
</comA>

2. Sehen Sie die Essenz durch das Phänomen

Die Rolle von Slots besteht darin, eine Inhaltsverteilung zu erreichen. Um eine Inhaltsverteilung zu erreichen, sind zwei Bedingungen erforderlich:

  • Platzhalter
  • Inhalte verteilen

slot -Tag kann als Platzhalter verstanden werden, und der Slot-Inhalt in der übergeordneten Komponente ist der zu verteilende Inhalt. Der Kern der Slot-Verarbeitung besteht darin, den angegebenen Inhalt an der angegebenen Stelle zu platzieren. Ohne weitere Umschweife erfahren Sie aus diesem Artikel:

  • Das Implementierungsprinzip von Slots
  • So verwenden Sie Slots in der render

3. Umsetzungsprinzip

Die Reihenfolge der Instanziierung von vue Komponenten ist: Statusinitialisierung der übergeordneten Komponente ( data , computed , watch …) --> Vorlagenkompilierung --> render generieren --> Rendering- watcher instanziieren --> render aufrufen, VNode generieren --> patch VNode , in echtes DOM konvertieren --> untergeordnete Komponente instanziieren --> ... denselben Vorgang wiederholen --> das von der untergeordneten Komponente generierte echte DOM wird auf dem echten DOM gemountet, das von der übergeordneten Komponente generiert und auf der Seite gemountet wurde --> alten Knoten entfernen

Aus dem obigen Prozess können wir Folgendes schließen:

1. Die Vorlage der übergeordneten Komponente wird vor der untergeordneten Komponente analysiert, sodass die übergeordnete Komponente zuerst den Inhalt der Slot-Vorlage erhält

2. Die Vorlage der Unterkomponente wird später analysiert. Wenn die Unterkomponente also render aufruft, um VNode zu generieren, können Sie VNode Knoten des Slots mithilfe einiger Mittel abrufen.

3. Der Bereichssteckplatz kann Variablen in der Unterkomponente abrufen, sodass die VNode Generierung des Bereichssteckplatzes dynamisch ist, dh scope der Unterkomponente muss in Echtzeit übergeben werden

Die gesamte Slot-Verarbeitungsphase gliedert sich grob in drei Schritte:

  • Kompilieren
  • Rendering-Vorlage generieren
  • VNode generieren

Anhand des folgenden Codes als Beispiel wird der Betriebsvorgang des Steckplatzes kurz erläutert.

<div id='App'>
  <Prüfung>
    <template slot="hallo">
      123
    </Vorlage>
  </Prüfung>
</div>
<Skript>
  neuer Vue({
    el: '#app',
    Komponenten:
      prüfen: {
        Vorlage: '<h1>' +
          '<slot name="hallo"></slot>' +
          '</h1>'
      }
    }
  })
</Skript>

4. Kompilierungsphase der übergeordneten Komponente

Beim Kompilieren wird die Vorlagendatei in einen AST Syntaxbaum analysiert und die Slot template in die folgende Datenstruktur analysiert:

{
  Schlagwort: 'Test',
  scopedSlots: { // Bereichsslot // Slotname: ASTNode,
    // ...
  }
  Kinder: [
    {
      Tag: 'Vorlage',
      // ...
      übergeordneter Knoten: übergeordneter ASTNode,
      children: [ childASTNode ], // Slot-Inhalt untergeordneter Knoten, d. h. Textknoten 123
      slotScope: nicht definiert, // Bereichsslot-Bindungswert slotTarget: "\"hallo\"", // Benannter Slotname slotTargetDynamic: false // Ist es ein dynamisch gebundener Slot// ...
    }
  ]
}

5. Die übergeordnete Komponente generiert eine Rendering-Methode

Gemäß dem AST Syntaxbaum wird die Zeichenfolge der Rendering-Methode analysiert und generiert. Das von der übergeordneten Komponente generierte Endergebnis lautet wie folgt. Diese Struktur entspricht dem direkten Schreiben render Methode. Das Wesentliche besteht darin, VNode zu generieren, aber _c oder h ist die Abkürzung von this.$createElement .

mit(diesem){
  return _c('div',{attrs:{"id":"app"}},
  [_c('Prüfung',
    [
      _c('template',{slot:"hallo"},[_v("\n 123\n ")])],2)
    ],
  1)
}

6. Übergeordnete Komponente generiert VNode

Rufen Sie die render auf, um VNode zu generieren. Das spezifische Format VNode ist wie folgt:

{
  Tag: 'div',
  Elternteil: undefiniert,
  data: { // VNode-Konfigurationselemente speichern attrs: { id: '#app' }
  },
  Kontext: Komponentenkontext, // Komponentenbereich elm: nicht definiert, // echtes DOM-Element untergeordnete Elemente: [
    {
      Tag: 'vue-component-1-test',
      children: undefined, // Die Komponente ist die kleinste Einheit der Seite, und der Slot-Inhalt wird in der untergeordneten Komponente analysiert parent: undefined,
      componentOptions: { // Komponentenkonfigurationselement Ctor: VueComponentCtor, // Komponentenkonstruktionsmethode data: {
          Haken: {
            init: fn, //Komponente instanziieren, die die Methode aufruft insert: fn,
            Vorpatch: fn,
            zerstören: fn
          },
          scopedSlots: { //Scope-Slot-Konfigurationselement, wird zum Generieren von Scope-Slot-VNode verwendet
            Steckplatzname: SteckplatzFn
          }
        },
        untergeordnete Elemente: [ // Komponenten-Slot-Knoten-Tag: 'Vorlage',
          propsData: undefiniert, // Props-Parameter-Listener: undefiniert,
          Daten: {
            Slot: "Hallo"
          },
          untergeordnete Elemente: [ VNode ],
          Elternteil: undefiniert,
          Kontext: Komponentenkontext // Geltungsbereich der übergeordneten Komponente // ...
        ] 
      }
    }
  ],
  // ...
}

In vue sind Komponenten die Grundeinheiten der Seitenstruktur. Aus dem obigen VNode können wir auch erkennen, dass VNode Seitenhierarchie bei test endet und test Verarbeitung der children während des Initialisierungsprozesses der Unterkomponente erfolgt. Die Zusammenstellung der Unterkomponenten-Konstruktionsmethode und die Zusammenführung der Attribute erfolgen in der createComponent Methode von vue-dev\src\core\vdom\create-component.js und der Aufrufeintrag für die Komponenteninstanzierung befindet sich in der createComponent Methode von vue-dev\src\core\vdom\patch.js.

7. Initialisierung des Unterkomponentenstatus

Beim Instanziieren einer Unterkomponente wird der Unterkomponenten-Slot-Knoten in initRender -> resolveSlots in der Form vm vm.$slots = {slotName: [VNode]} der Komponentenbereichs-VM bereitgestellt.

8. Kompilierungsphase der Unterkomponenten

Während der Kompilierungsphase kompiliert die Unterkomponente slot -Knoten in die folgende AST Struktur:

{
  tag: 'h1',
  Elternteil: undefiniert,
  Kinder: [
    {
      Schlagwort: 'Slot',
      Slotname: "\"Hallo\"",
      // ...
    }
  ],
  // ...
}

9. Rendering-Methode zur Generierung von Unterkomponenten

Die generierte Rendering-Methode lautet wie folgt, wobei _t die Abkürzung renderSlot -Methode ist. Über renderSlot -Methode können wir den Slot-Inhalt intuitiv mit dem Slot-Punkt verknüpfen.

// Rendering-Methode mit (diesem) {
  return _c('h1',[ _t("hallo") ], 2)
}
// Quellcodepfad: vue-dev\src\core\instance\render-helpers\render-slot.js
Exportfunktion RenderSlot (
  Name: Zeichenfolge,
  Fallback: ?Array<VNode>,
  Requisiten: ?Objekt,
  bindObject: ?Objekt
): ?Array<VNode> {
  const scopedSlotFn = this.$scopedSlots[name]
  let-Knoten
  if (scopedSlotFn) { // Slot mit Gültigkeitsbereich
    Requisiten = Requisiten || {}
    wenn (Bindeobjekt) {
      wenn (Prozess.env.NODE_ENV !== 'Produktion' && !isObject(bindObject)) {
        warnen(
          'Slot V-Bind ohne Argument erwartet ein Objekt',
          Das
        )
      }
      Requisiten = erweitern(erweitern({}, bindObject), Requisiten)
    }
    //Slot erweitern, Slot-VNode abrufen
    Knoten = scopedSlotFn(Eigenschaften) || Fallback
  } anders {
    // Holen Sie sich den Steckplatz normalen Steckplatz VNode
    Knoten = dies.$slots[Name] || Fallback
  }

  const Ziel = Requisiten && Requisiten.Slot
  wenn (Ziel) {
    gib dies zurück. $createElement('template', { slot: target }, nodes)
  } anders {
    Rückgabeknoten
  }
}

Unterschied zwischen Scoped Slots und Named Slots

<!-- Demo -->
<div id='App'>
  <Prüfung>
      <template slot="hallo" slot-scope='Umfang'>
        {{scope.hello}}
      </Vorlage>
  </Prüfung>
</div>
<Skript>
    var vm = neuer Vue({
        el: '#app',
        Komponenten:
            prüfen: {
                Daten () {
                    zurückkehren {
                        hallo: '123'
                    }
                },
                Vorlage: '<h1>' +
                    '<slot name="hallo" :hallo="hallo"></slot>' +
                  '</h1>'
            }
        }
    })

</Skript>

Der Hauptunterschied zwischen Slots mit Gültigkeitsbereich und normalen Slots besteht darin, dass der Slot-Inhalt Variablen mit Gültigkeitsbereich für Unterkomponenten erhalten kann. Aufgrund der Notwendigkeit, Unterkomponentenvariablen einzufügen, unterscheiden sich bereichsbezogene Slots in den folgenden Punkten von benannten Slots:

Beim Zusammenstellen der Rendering-Methode generiert der Bereichsslot eine Methode, die den Injektionsbereich enthält. Im Vergleich zu createElement zum Generieren von VNode gibt es eine zusätzliche Schicht von Injektionsbereichsmethoden-Wrapping, die bestimmt, dass der Bereichsslot VNode generiert wird, wenn die untergeordnete Komponente VNode generiert, und der benannte Slot generiert wird, wenn die übergeordnete Komponente VNode erstellt. _u steht für resolveScopedSlots , wodurch das Knotenkonfigurationselement in die Form {scopedSlots: {slotName: fn}} konvertiert wird.

mit (diesem) {
        return _c('div', {
            Attribute: {
                "id": "App"
            }
        }, [_c('test', {
            Bereichsslots: _u([{
                Taste: "Hallo",
                fn: Funktion (Umfang) {
                    return [_v("\n " + _s(scope.hello) + "\n ")]
                }
            }])
        })], 1)
    }

Wenn die Unterkomponente initialisiert wird, wird der benannte Slot-Knoten verarbeitet und an die Komponente $slots angehängt, und der Slot mit Gültigkeitsbereich wird direkt in renderSlot aufgerufen.

Abgesehen davon ist der Vorgang ziemlich gleich. Der Mechanismus der Slots ist nicht schwer zu verstehen, der Schlüssel liegt jedoch in den beiden Schritten der Vorlagenanalyse und der Generierung von Rendering-Funktionen, die komplexer sind, einen längeren Prozess umfassen und schwieriger zu verstehen sind.

10. Nutzungstipps

Durch die obige Analyse können wir den Slot-Verarbeitungsablauf grob verstehen. Die meiste Arbeit wird mit Vorlagen zum Schreiben vue -Code erledigt, manchmal unterliegen Vorlagen jedoch bestimmten Einschränkungen, und es ist erforderlich, render zu verwenden, um die Komponentenabstraktionsfunktionen von vue zu erweitern. Dann verwenden wir in der render den Slot wie folgt:

10.1. Benannte Slots

Die Slot-Verarbeitung gliedert sich im Allgemeinen in zwei Teile:

  • Übergeordnete Komponente: Die übergeordnete Komponente muss nur als aus der Vorlage kompilierte Rendering-Methode geschrieben werden, d. h. den slot -Namen angeben
  • Unterkomponente: Da die Unterkomponente VNode direkt übernimmt, muss die Unterkomponente nur slot -Tag durch VNode ersetzen. Die Unterkomponente wird den benannten Slot bei der Initialisierung in das Komponentenattribut $slots einbinden.
<div id='App'>
<!-- <Prüfung>-->
<!-- <template slot="hallo">-->
<!-- 123-->
<!-- </template>-->
<!-- </test>-->
</div>
<Skript>
  neuer Vue({
    // el: '#app',
    rendern (Element erstellen) {
      returniere createElement('test', [
        Element erstellen('h3', {
          Slot: 'Hallo',
          domProps: {
            innererText: '123'
          }
        })
      ])
    },
    Komponenten:
      prüfen: {
        rendern(Element erstellen) {
          returniere createElement('h1', [this.$slots.hello]);
        }
        // Vorlage: '<h1>' +
        // '<slot name="hallo"></slot>' +
        // '</h1>'
      }
    }
  }).$mount('#app')
</Skript>

10.2. Slots mit begrenztem Gültigkeitsbereich

Bereichsbezogene Slots sind flexibler zu verwenden und können Zustände von Unterkomponenten einfügen. Scoped Slots + render sind sehr nützlich für die Kapselung sekundärer Komponenten. Beispielsweise sind bereichsbezogene Slots sehr nützlich, wenn Sie ElementUI table basierend auf JSON -Daten kapseln.

<div id='App'>
<!-- <Prüfung>-->
<!-- <span slot="hallo" slot-scope='scope'>-->
<!-- {{scope.hello}}-->
<!-- </span>-->
<!-- </test>-->
</div>
<Skript>
  neuer Vue({
    // el: '#app',
    rendern (Element erstellen) {
      returniere Element erstellen('test', {
        Bereichsslots: {
          hallo: scope => { // In der Rendering-Methode der übergeordneten Komponente stimmt die endgültig konvertierte Scope-Slot-Methode mit dieser Schreibmethode überein return createElement('span', {
              domProps: {
                innererText: Umfang.hallo
              }
            })
          }
        }
      })
    },
    Komponenten:
      prüfen: {
        Daten () {
          zurückkehren {
            hallo: '123'
          }
        },
        rendern (Element erstellen) {
          // Die übergeordnete Komponente des Scope-Slots übergibt eine Funktion, die manuell aufgerufen werden muss, um einen VNode zu generieren
          let slotVnode = this.$scopedSlots.hello({ hallo: this.hello })
          returniere createElement('h1', [ slotVnode ])
        }
        // Vorlage: '<h1>' +
        // '<slot name="hallo" :hallo="hallo"></slot>' +
        // '</h1>'
      }
    }
  }).$mount('#app')

</Skript>

Oben wird kurz der detaillierte Inhalt des Implementierungsprinzips von Vue-Slots erläutert. Weitere Informationen zu Vue-Slots finden Sie in den anderen verwandten Artikeln auf 123WORDPRESS.COM!

Das könnte Sie auch interessieren:
  • Analyse eines Beispiels zur Verwendung von Slots für Vue-Lernnotizen
  • Vue-Lernhinweise: Grundlegende Anwendungsbeispielanalyse von Slot-Slots
  • Vue-Lernnotizen, Umfang, Slot, Beispielanalyse
  • $slot in vue ruft die Knoteninstanz des Slots ab
  • Verwenden Sie den Reaktionskontext, um die Vue-Slot-Funktion zu implementieren
  • Eine kurze Analyse des Verständnisses von Vue-Slots und Scoped-Slots
  • Zusammenführungs- und Überschreibverhalten von anonymen Slots und Slots mit begrenztem Gültigkeitsbereich in Vue
  • Detaillierte Erklärung zur Verwendung von anonymen, benannten und bereichsbezogenen Slots in Vue
  • Detaillierte Erklärung zur Verwendung von Slots und Cluster-Slots in Vue
  • Vue-Slots verstehen und verwenden

<<:  Eine benutzerfreundliche Alternative in Linux (Befehl fd)

>>:  Verwenden von Puppeteer zum Implementieren der Screenshot-Funktion für Webseiten unter Linux (CentOS)

Artikel empfehlen

Implementierung des Wasserfall-Layouts im Uni-App-Projekt

GitHub-Adresse, Sie können es mit einem Stern mar...

Reines CSS zum Hinzufügen von Stil zur ausgewählten Implementierung (kein Skript)

Ändern Sie den Standardstil der Auswahl, normalerw...

Erläuterung der Methode zum Schreiben von SQL-Anweisungen zum Einfügen

Methode 1: INSERT INTO t1(Feld1,Feld2) VALUE(v001...

CSS3 erzielt einen unendlichen Scroll-/Karusselleffekt der Liste

Effektvorschau Ideen Scrollen Sie durch die aktue...

Detaillierte Erklärung der Primärschlüssel und Transaktionen in MySQL

Inhaltsverzeichnis 1. Kommentare zu MySQL-Primärs...

Detaillierte Schritte zum Konfigurieren von my.ini für mysql5.7 und höher

Im entpackten Paket von Windows 64-Bit MySQL 5.7 ...

Vue3 setup() - Erweiterte Verwendungsbeispiele - ausführliche Erklärung

Inhaltsverzeichnis 1. Unterschiede zwischen Optio...

Was sind HTML-Inline-Elemente und Block-Level-Elemente und ihre Unterschiede

Ich erinnere mich an eine Frage, die der Intervie...