Funktionsprinzip und Implementierungsmethode der Vue-Anweisung

Funktionsprinzip und Implementierungsmethode der Vue-Anweisung

Einführung in Vue

Die aktuelle Ära der großen Front-Ends ist eine Ära der Turbulenzen und Konflikte. Die Welt ist in viele Fraktionen aufgeteilt, die hauptsächlich von Vue, React und Angular angeführt werden, wodurch eine dreibeinige Situation von Front-End-Frameworks entsteht. Die Position von Vue im Front-End-Framework ähnelt der von jQuery in der Vergangenheit. Aufgrund seiner Einfachheit und hohen Entwicklungseffizienz ist es zu einer der wesentlichen Fähigkeiten für Front-End-Ingenieure geworden.

Vue ist ein fortschrittliches JavaScript-Framework, das Plug-Ins von Drittanbietern und UI-Komponentenbibliotheken perfekt integriert. Der größte Unterschied zu jQuery besteht darin, dass Vue den Seiten-Rendering-Inhalt ändern kann, ohne dass Entwickler DOM-Knoten direkt manipulieren müssen. Auf der Grundlage von bestimmten HTML-, CSS- und JavaScript-Kenntnissen können Anwendungsentwickler schnell loslegen und elegante und prägnante Anwendungsmodule entwickeln.

Vorwort

Benutzerdefinierte Anweisungen werden in Vue nach Komponenten am zweithäufigsten verwendet. Sie umfassen fünf Lebenszyklus-Hooks: bind , inserted , update , componentUpdated und unbind . In diesem Artikel wird das Funktionsprinzip von Vue-Direktiven vorgestellt. In diesem Artikel erfahren Sie:

  • So funktioniert die Richtlinie
  • Hinweise zur Verwendung von Anweisungen

Grundlegende Verwendung

Offizielle Website Fall:

<div id='App'>
  <Eingabetyp="Text" v-Modell="Eingabewert" v-Fokus>
</div>
<Skript>
  Vue.direktive('Fokus', {
    // Rufe bind() auf, wenn du ein Element zum ersten Mal bindest {
      console.log('binden')
    },
    // Wenn das gebundene Element in das DOM eingefügt wird ...
    eingefügt: Funktion (el) {
      console.log('eingefügt')
      el.fokus()
    },
    // Rufe update() auf, wenn die Komponente VNode aktualisiert ist {
      console.log('aktualisieren')
    },
    // Rufen Sie componentUpdated() auf, nachdem alle VNode und seine untergeordneten VNodes der Komponente, in der sich die Anweisung befindet, aktualisiert wurden {
      console.log('Komponente aktualisiert')
    },
    // Wird nur einmal aufgerufen. unbind() wird aufgerufen, wenn die Anweisung vom Element { gelöst wird.
      console.log('aufheben')
    }
  })
  neuer Vue({
    Daten: {
      Eingabewert: ''
    }
  }).$mount('#app')
</Skript>

So funktioniert der Befehl

Initialisierung

Rufen Sie beim Initialisieren der globalen API unter platforms/web createPatchFunction auf, um die Patch-Methode zu generieren, die VNode in das echte DOM konvertiert. Ein wichtiger Schritt bei der Initialisierung ist die Definition der Hook-Methoden, die den DOM-Knoten entsprechen. Während der DOM-Erstellung (create), Aktivierung (avtivate), Aktualisierung (update), Entfernung (remove) und Zerstörung (destroy) werden die entsprechenden Hook-Methoden abgefragt und jeweils aufgerufen. Einige dieser Hooks sind die Eingänge zum Befehlsdeklarationszyklus.

// src/core/vdom/patch.js
const hooks = ['erstellen', 'aktivieren', 'aktualisieren', 'entfernen', 'zerstören']
Exportfunktion createPatchFunction (Backend) {
  sei i, j
  const cbs = {}

  const { module, nodeOps } = backend
  für (i = 0; i < hooks.length; ++i) {
    cbs[Haken[i]] = []
    // Module entsprechen Modulen in Vue, einschließlich Klasse, Stil, DomListener, DomProps, Attrs, Direktive, Ref, Übergang
    für (j = 0; j < Module.Länge; ++j) {
      wenn (isDef(Module[j][Hooks[i]])) {
        // Schließlich Hooks in {hookEvent: [cb1, cb2 ...], ...} von cbs[hooks[i]].push(modules[j][hooks[i]]) umwandeln.
      }
    }
  }
  // ....
  Rückgabefunktionspatch (alterVnode, vnode, hydratisieren, nur entfernen) {
    // ...
  }
}

Vorlagenkompilierung

Die Vorlagenkompilierung dient zum Parsen der Anweisungsparameter. Das spezifische dekonstruierte ASTElement lautet wie folgt:

{
  Tag: 'Eingabe',
  übergeordnetes Element: ASTElement,
  Anweisungen: [
    {
      arg: null, // Parameterende: 56, // Endzeichenposition der Anweisung isDynamicArg: false, // dynamischer Parameter, v-xxx[dynamicParams]='xxx' Formaufrufmodifikatoren: nicht definiert, // Name des Anweisungsmodifikators: „model“,
      rawName: "v-model", // Befehlsname Start: 36, // Befehlsstartzeichenposition Wert: "inputValue" // Vorlage },
    {
      arg: null,
      Ende: 67,
      isDynamicArg: false,
      Modifikatoren: undefiniert,
      Name: "Fokus",
      Rohname: "v-focus",
      Beginn: 57,
      Wert: ""
    }
  ],
  // ...
}

Rendering-Methode generieren

Vue empfiehlt die Verwendung von Direktiven zum Bedienen von DOM. Da benutzerdefinierte Direktiven DOM oder Attribute ändern können, vermeiden Sie die Auswirkungen von Direktiven auf die Vorlagenanalyse. Beim Generieren von Rendering-Methoden werden als Erstes Direktiven wie v-model verarbeitet, was im Wesentlichen ein syntaktischer Zucker ist. Beim Spleißen von Rendering-Funktionen werden den Elementen Wertattribute und Eingabeereignisse hinzugefügt (am Beispiel von „input“ kann dies auch vom Benutzer angepasst werden).

mit (diesem) {
    return _c('div', {
        Attribute: {
            "id": "App"
        }
    }, [_c('Eingabe', {
        Anweisungen: [{
            Name: "Modell",
            rawName: "v-Modell",
            Wert: (Eingabewert),
            Ausdruck: "Eingabewert"
        }, {
            Name: "Fokus",
            Rohname: "v-focus"
        }],
        Attribute: {
            "Typ": "Text"
        },
        domProps: {
            "value": (inputValue) // Attribute, die bei der Verarbeitung von v-model-Anweisungen hinzugefügt werden},
        An: {
            "input": function($event) { // Benutzerdefiniertes Ereignis, das bei der Verarbeitung der V-Model-Direktive hinzugefügt wird, wenn ($event.target.composing)
                    zurückkehren;
                Eingabewert = $event.target.value
            }
        }
    })])
}

VNode generieren

Das Design der Vue-Direktiven soll uns die Manipulation von DOM erleichtern. Beim Generieren von VNode führen die Direktiven keine zusätzliche Verarbeitung durch.

Generieren eines echten DOM

Während des Vue-Initialisierungsprozesses müssen wir zwei Punkte beachten:

  • Die Initialisierung des Status ist übergeordnet -> untergeordnet, z. B. beforeCreate, created, beforeMount, die Aufrufreihenfolge ist übergeordnet -> untergeordnet
  • Die Montagereihenfolge des echten DOM ist Kind -> Elternteil, z. B. montiert. Dies liegt daran, dass beim Generieren des echten DOM, wenn eine Komponente angetroffen wird, der Komponentenerstellungsprozess befolgt wird. Die Generierung des echten DOM wird Ebene für Ebene vom Kind zum Elternteil gespleißt.

Während des Patch-Prozesses wird jedes Mal, wenn createElm aufgerufen wird, um das echte DOM zu generieren, festgestellt, ob der aktuelle VNode ein Datenattribut hat. Wenn dies der Fall ist, wird invokeCreateHooks aufgerufen, um die am Anfang erstellte Hook-Funktion auszuführen. Der Kerncode lautet wie folgt:

// src/core/vdom/patch.js
Funktion createElm (
    vKnoten,
    eingefügteVnodeQueue,
    übergeordnete Ulme,
    sieheElm,
    verschachtelt,
    BesitzerArray,
    Index
  ) {
    // ...
    // createComponent hat einen Rückgabewert, also die Methode zum Erstellen von Komponenten. Wenn es keinen Rückgabewert gibt, fahren Sie mit der folgenden Methode fort, if (createComponent(vnode, insertedVnodeQueue, parentElm, refElm)) {
      zurückkehren
    }

    const data = vnode.data
    // ....
    wenn (isDef(Daten)) {
        // Nachdem der reale Knoten erstellt wurde, aktualisiere die Knotenattribute, einschließlich der Anweisung // Die Anweisung ruft die Bind-Methode zum ersten Mal auf und initialisiert dann die nachfolgende Hook-Methode der Anweisung invokeCreateHooks(vnode, insertedVnodeQueue)
    }
    // Von unten nach oben, einfügen(parentElm, vnode.elm, refElm)
    // ...
  }

Oben sehen Sie den ersten Eintrag der Direktiven-Hook-Methode. Es ist an der Zeit, das Geheimnis von directive.js zu lüften. Der Kerncode lautet wie folgt:

// src/core/vdom/modules/directives.js

// Standardmäßig sind alle ausgelösten Methoden updateDirectives method export default {
  erstellen: updateDirectives,
  aktualisieren: Update-Richtlinien,
  zerstören: Funktion unbindDirectives (vnode: VNodeWithData) {
    // Wenn zerstört, vnode === emptyNode
    Update-Direktiven(vnode, leererKnoten)
  }
}

Funktion updateDirectives (alter Vnode: VNodeWithData, vnode: VNodeWithData) {
  wenn (alteVnode.data.directives || vnode.data.directives) {
    _update(alterVnode, vnode)
  }
}

Funktion _update (alterVnode, vnode) {
  const isCreate = alterVnode === leererNode
  const isDestroy = vnode === leerer Knoten
  const oldDirs = normalizeDirectives(alterVnode.data.directives, alterVnode.context)
  const newDirs = normalizeDirectives(vnode.data.directives, vnode.context)
  // Rückruf nach dem Einfügen const dirsWithInsert = [
  // Rückruf nach Abschluss des Updates const dirsWithPostpatch = []

  let-Schlüssel, oldDir, dir
  für (Schlüssel in newDirs) {
    oldDir = oldDirs[Schlüssel]
    dir = newDirs[Schlüssel]
    // Neuer Elementbefehl, führt die eingefügte Hook-Methode einmal aus, wenn (!oldDir) {
      // neue Direktive, binden
      callHook(dir, 'binden', vnode, alter Vnode)
      if (dir.def && dir.def.inserted) {
        dirsWithInsert.push(dir)
      }
    } anders {
      // bestehende Direktive, Update
      // Wenn das Element bereits existiert, wird die componentUpdated-Hook-Methode dir.oldValue = oldDir.value einmal ausgeführt
      dir.oldArg = altesDir.arg
      callHook(dir, 'update', vnode, alter vnode)
      wenn (dir.def && dir.def.componentUpdated) {
        dirsWithPostpatch.push(dir)
      }
    }
  }

  if (dirsWithInsert.length) {
    // Das echte DOM wird in die Seite eingefügt und diese Callback-Methode wird aufgerufen const callInsert = () => {
      für (lass i = 0; i < dirsWithInsert.length; i++) {
        callHook(dirsWithInsert[i], 'eingefügt', vnode, alterVnode)
      }
    }
    // VNode Merge-Insert-Hooks
    wenn (ist erstellt) {
      mergeVNodeHook(vnode, 'insert', callInsert)
    } anders {
      callInsert()
    }
  }

  if (dirsWithPostpatch.Länge) {
    mergeVNodeHook(vnode, 'postpatch', () => {
      für (lass i = 0; i < dirsWithPostpatch.length; i++) {
        callHook(dirsWithPostpatch[i], 'Komponente aktualisiert', vnode, alter Vnode)
      }
    })
  }

  wenn (!istErstellen) {
    für (Schlüssel in oldDirs) {
      wenn (!newDirs[Schlüssel]) {
        // nicht mehr vorhanden, Bindung aufheben
        callHook(alteDirs[Schlüssel], 'aufheben', alterV-Knoten, alterV-Knoten, isDestroy)
      }
    }
  }
}

Bei der ersten Erstellung läuft die Ausführung folgendermaßen ab:

  1. oldVnode === emptyNode, isCreate ist true und alle Bind-Hook-Methoden im aktuellen Element werden aufgerufen.
  2. Überprüfen Sie, ob die Direktive einen inserted -Hook enthält. Wenn ja, fügen Sie den Insert-Hook in VNode.data.hooks ein.
  3. Nachdem die DOM-Montage abgeschlossen ist, wird invokeInsertHook für alle montierten Knoten ausgeführt, wenn ein Insert-Hook in VNode.data.hooks vorhanden ist. Es wird aufgerufen und die an die Anweisung gebundene eingefügte Methode wird ausgelöst.

Im Allgemeinen werden für die erste Erstellung nur die Methoden bind und inserted verwendet, während update und componentUpdated den Methoden „Bind“ und „Insert“ entsprechen. Wenn sich der Abhängigkeitsstatus der Komponente ändert, wird VNode diff Algorithmus zum Patchen des Knotens verwendet. Der Aufrufvorgang läuft wie folgt ab:

  1. Wenn sich die Reaktionsdaten ändern, rufen Sie dep.notify auf, um über Datenaktualisierungen zu benachrichtigen.
  2. Rufen Sie patchVNode auf, um differenzielle Aktualisierungen an den neuen und alten VNodes durchzuführen und die aktuellen VNode-Attribute vollständig zu aktualisieren (einschließlich Anweisungen, die in die Methode updateDirectives gelangen).
  3. Wenn die Direktive eine Update-Hook-Methode hat, rufen Sie die Update-Hook-Methode auf, initialisieren Sie den componentUpdated -Rückruf und mounten Sie die Postpatch-Hooks in VNode.data.hooks .
  4. Nachdem der aktuelle Knoten und seine untergeordneten Knoten aktualisiert wurden, werden postpatch hooks ausgelöst, d. h. die componentUpdated-Methode der Direktive

Der Kerncode lautet wie folgt:

// src/core/vdom/patch.js
Funktion patchVnode (
    alterVnode,
    vKnoten,
    eingefügteVnodeQueue,
    BesitzerArray,
    Index,
    Nur entfernen
  ) {
    // ...
    const oldCh = oldVnode.children
    const ch = vnode.children
    // Knotenattribute vollständig aktualisieren if (isDef(data) && isPatchable(vnode)) {
      für (i = 0; i < cbs.update.length; ++i) cbs.update[i](alterVnode, vnode)
      wenn (isDef(i = data.hook) und isDef(i = i.update)) i(alterVnode, vnode)
    }
    // ...
    wenn (isDef(Daten)) {
    // Postpatch-Hook aufrufen, wenn (isDef(i = data.hook) und isDef(i = i.postpatch)) i(oldVnode, vnode)
    }
  }

Die Methode „unbind“ ruft „ invokeDestroyHook auf, wenn der Knoten zerstört wird. Dies wird hier nicht näher beschrieben.

Vorsichtsmaßnahmen

Bei der Verwendung benutzerdefinierter Anweisungen unterscheidet sich das V-Modell immer noch von der normalen Datenbindung von Vorlagen. Obwohl beispielsweise der von mir übergebene Parameter (v-xxx='param') ein Referenztyp ist, kann er bei Datenänderungen weder das Binden noch das Einfügen der Anweisung auslösen. Dies liegt daran, dass im Deklarationszyklus der Anweisung Binden und Einfügen nur einmal bei der Initialisierung aufgerufen werden und danach nur noch update und componentUpdated verwendet werden.

Die Ausführungsreihenfolge im Deklarationslebenszyklus einer Direktive lautet bind -> inserted -> update -> componentUpdated . Wenn eine Direktive vom Inhalt einer untergeordneten Komponente abhängen muss, wird empfohlen, die entsprechende Geschäftslogik in componentUnpdated zu schreiben.

In Vue werden viele Methoden in einer Schleife aufgerufen, z. B. Hook-Methoden, Event-Callbacks usw. Im Allgemeinen werden die Aufrufe in Try-Catch gekapselt. Dies soll verhindern, dass eine Verarbeitungsmethode einen Fehler meldet und das gesamte Programm zum Absturz bringt. Dies kann als Referenz in unserem Entwicklungsprozess verwendet werden.

Zusammenfassung

Als ich begann, mir den gesamten Vue-Quellcode anzusehen, verstand ich viele Details und Methoden nicht. Indem ich die Implementierung jeder einzelnen Funktion klärte, konnte ich nach und nach das Gesamtbild von Vue erkennen und gleichzeitig einige Fallstricke bei der Entwicklung und Verwendung vermeiden.

GitHub

Oben ist der detaillierte Inhalt der Implementierungsmethode des Arbeitsprinzips der Vue-Direktive. Weitere Informationen zum Prinzip der Vue-Direktive finden Sie in den anderen verwandten Artikeln auf 123WORDPRESS.COM!

Das könnte Sie auch interessieren:
  • Eine kurze Erläuterung des Implementierungsprinzips der Vue v-model-Direktive
  • Detaillierte Erläuterung der grundlegenden Verwendung von Anweisungen zur V-On-Ereignisüberwachung in Vue
  • Grundlegendes zur dynamischen Attributdatenbindung von Vue (v-bind-Anweisung) in einem Artikel
  • Lösung für die Unfähigkeit, den Stil des von Vue gerenderten Rich-Texts durch V-HTML-Anweisungen zu ändern
  • Eine kurze Erläuterung zur Verwendung der Vue-Ankerdirektive v-anchor

<<:  Beheben Sie den Fehler bei der Installation von VMware Tools unter Ubuntu 18.04

>>:  Einige Hinweise zum Ändern des innodb_data_file_path-Parameters von MySQL

Artikel empfehlen

Allgemeine Betriebsbefehle von MySQL im Linux-System

Aufschlag: # chkconfig --list Alle Systemdienste ...

Neuer Ansatz zum Umschalten der Tab-Leiste mit zwei Auswahlmöglichkeiten in Vue

Problembeschreibung Wenn wir an einem Projekt arb...

Codebeispiele für die Sicherung mehrerer MySQL-Datenbanken

In diesem Artikel werden hauptsächlich Codebeispi...

Schritt-für-Schritt-Anleitung zum Erstellen einer Kalenderkomponente mit React

Inhaltsverzeichnis Betriebswirtschaftlicher Hinte...

Die Verwendung von Textbereichen in HTML und häufige Probleme und Fallanalyse

Der Textarea-Tag ist ein HTML-Tag, den wir häufig ...

Hauptfunktionen von MySQL Innodb: Einfügepuffer

Inhaltsverzeichnis Was ist ein Einfügepuffer? Was...

18 Sets exquisiter kostenloser Symbolmaterialien im Apple-Stil zum Teilen

Apple-Becher-Symbole und Extras HD StorageBox – Z...

So installieren Sie Redis5.0.3 im Docker

1. Ziehen Sie das offizielle 5.0.3-Image [root@lo...