VorwortZusätzlich zu den standardmäßig integrierten Anweisungen für die Kernfunktionalität (v-model und v-show) können Sie in Vue auch benutzerdefinierte Anweisungen registrieren. Die Einführung auf der offiziellen Website ist relativ abstrakt und wirkt sehr großartig. Mein persönliches Verständnis von benutzerdefinierten Anweisungen besteht darin, dass, wenn benutzerdefinierte Anweisungen auf einige DOM-Elemente oder -Komponenten einwirken, das Element beim ersten Rendern, Einfügen in den übergeordneten Knoten, Aktualisieren oder Aufheben der Bindung bestimmte Vorgänge (Hook-Funktion ()) ausführen kann. Es gibt zwei Möglichkeiten, benutzerdefinierte Anweisungen zu registrieren. Eine davon ist die globale Registrierung, bei der Vue.directive (Anweisungsname, Konfigurationsparameter) zur Registrierung verwendet wird. Nach der Registrierung können alle Vue-Instanzen sie verwenden. Die andere ist die lokale Registrierung. Beim Erstellen einer Vue-Instanz wird eine lokale Anweisung über das Attribut „directives“ erstellt. Lokale benutzerdefinierte Anweisungen können nur in der aktuellen Vue-Instanz verwendet werden. Benutzerdefinierte Anweisungen können an die folgenden Hook-Funktionen gebunden werden:
Jede Hook-Funktion kann vier Parameter haben, nämlich el (entsprechende DOM-Knotenreferenz), binding (einige erweiterte Informationen über die Anweisung, ein Objekt), vnode (der dem Knoten entsprechende virtuelle VNode) und oldVnode (der vorherige VNode, nur in den Hooks update und componentUpdated verfügbar). Wenn die Bind-Hook-Funktion ausgeführt wird, wird das DOM-Element gerendert, aber nicht in das übergeordnete Element eingefügt, zum Beispiel: <!DOCTYPE html> <html lang="de"> <Kopf> <meta charset="UTF-8"> <title>Dokument</title> <script src="vue.js"></script> </Kopf> <Text> <div id="d"><input type="" name="" v-fokus></div> <Skript> Vue.direktive('Fokus', { bind:function(el){console.log(el.parentElement);}, //Übergeordneten Knoten drucken eingefügt: function (el) {console.log(el.parentElement);el.focus()} //Übergeordneten Knoten drucken und das aktuelle Element fokussieren }) var app = neues Vue({el:"#d"}) </Skript> </body> </html> Die Ausgabe lautet wie folgt: Sie können sehen, dass das Eingabeelement automatisch den Fokus erhält und die Konsolenausgabe wie folgt lautet: Es ist ersichtlich, dass für den bind ()-Hook der übergeordnete Knoten nicht abgerufen werden kann, da Vue das aktuelle Element erst nach Ausführung des bind ()-Hooks in den untergeordneten Knoten des übergeordneten Elements einfügt. QuellcodeanalyseDie Funktion processAttrs() wird beim Parsen der Vorlage ausgeführt, um das DOM wie folgt in ein AST-Objekt zu konvertieren: Funktion processAttrs (el) { // Vue-Attribute analysieren var list = el.attrsList; var i, l, Name, Rohname, Wert, Modifikatoren, isProp; für (i = 0, l = Liste.Länge; i < l; i++) { //Jedes Attribut durchlaufen name = rawName = Liste[i].name; Wert = Liste[i].Wert; if (dirRE.test(name)) { //Wenn das Attribut mit v-, @ oder : beginnt, bedeutet dies, dass dies eine interne Vue-Direktive ist // Element als dynamisch markieren el.hasBindings = true; // Modifikatoren Modifikatoren = parseModifikatoren(Name); if (Modifikatoren) { Name = Name.Ersetzen(ModifikatorRE, ''); } if (bindRE.test(name)) { // v-bind //bindRD ist gleich /^:|^v-bind:/, d. h. wenn das Attribut eine v-bind-Anweisung ist /*v-bind-Zweig*/ } sonst wenn (onRE.test(name)) { // v-on /* Zweig von v-on */ } sonst { // normale Anweisungen name = name.replace(dirRE, ''); //Entfernen Sie das Befehlspräfix, z. B. ist v-show nach der Ausführung gleich show // Argument analysieren var argMatch = name.match(argRE); var arg = argMatch && argMatch[1]; wenn (arg) { Name = Name.Slice(0, -(Arg.Länge + 1)); } addDirective(el, Name, RawName, Wert, Argument, Modifikatoren); //Führen Sie addDirective aus, um ein Direktivenattribut zu el hinzuzufügen, wenn ("Entwicklung" !== 'Produktion' && Name === 'Modell') { checkForAliasModel(el, Wert); } } } anders { /*Nicht-Vue-Direktivenzweig*/ } } } addDirective fügt dem AST-Objekt ein Direktivenattribut hinzu, um die Anweisungsinformationen wie folgt zu speichern: Funktion addDirective ( // Zeile 6561 bezieht sich auf die Anweisung. Fügen Sie dem AST-Objekt el ein Direktivenattribut hinzu, wobei der Wert die Informationen der Anweisung el sind. Name, Rohname, Wert, arg, Modifikatoren ) { (el.directives || (el.directives = [])).push({ name: name, rawName: rawName, value: value, arg: arg, modifiers: modifiers }); el.plain = falsch; } Wenn das p-Element im Beispiel hier ausgeführt wird, sieht das entsprechende AST-Objekt wie folgt aus: Als nächstes wird, wenn generate die Rendre-Funktion generiert, die Funktion genDirectives() ausgeführt, um den AST wie folgt in eine Render-Funktion umzuwandeln: mit (diesem) {return _c ('div', {attrs: {"id": "d"}}, [_c ('input', {directives: [{name: "focus", rawName: "v-focus"}],attrs: {"type": "","name": "}})])} Schließlich wird nach Abschluss des Renderings die Funktion „Create Hook“ des Direktivenmoduls wie folgt ausgeführt: var directives = { //Zeile 6173 directives module create: updateDirectives, //Hook nach dem Erstellen von DOM update: updateDirectives, zerstören: Funktion unbindDirectives (vnode) { Update-Direktiven (vnode, leerer Knoten); } } function updateDirectives (oldVnode, vnode) { //Zeile 6181 oldVnode: alter Vnode, vnode nur verfügbar beim Aktualisieren: neuer VNode wenn (alteVnode.data.directives || vnode.data.directives) { _update(alterVnode, vnode); } } _updat wird zum Initialisieren und Aktualisieren der Verarbeitungsanweisungen wie folgt verwendet: function _update (oldVnode, vnode) { //Initialisierungs-/Aktualisierungsanweisung in Zeile 6187 var isCreate = oldVnode === emptyNode; //Ist es eine Initialisierung? var isDestroy = vnode === emptyNode; var oldDirs = normalizeDirectives$1(oldVnode.data.directives, oldVnode.context); var newDirs = normalizeDirectives$1(vnode.data.directives, vnode.context); //Rufen Sie die Funktion normalizeDirectives$1() auf, um Parameter zu normalisieren var dirsWithInsert = []; var dirsWithPostpatch = []; var Schlüssel, altesVerzeichnis, Verzeichnis; für (Schlüssel in newDirs) { //NewDirs durchlaufen oldDir = oldDirs[key]; //Schlüsseldirektive Informationen zu oldVnodedir = newDirs[key]; //Schlüsseldirektive Informationen zu vnodeif (!oldDir) { //Wenn oldDir nicht existiert, ist es eine neue Direktive// neue Direktive, bind callHook$1(dir, 'bind', vnode, oldVnode); //Rufe die Funktion callHook$1() auf, Parameter 2 ist „bind“, d. h. führe die Bind-Funktion der V-Focus-Anweisung aus, if (dir.def && dir.def.inserted) { //Wenn eine eingefügte Hook-Funktion definiert ist, dirsWithInsert.push(dir); //Speichere sie im Array dirsWithInsert} } anders { // bestehende Direktive, Update dir.alterWert = altesDir.Wert; callHook$1(dir, 'update', vnode, alter Vnode); wenn (dir.def && dir.def.componentUpdated) { dirsWithPostpatch.push(dir); } } } if (dirsWithInsert.length) { //Wenn dirsWithInsert existiert (das heißt, die eingefügte Hook-Funktion ist gebunden) var callInsert = function () { //Definiere eine callInsert-Funktion, die jede Funktion in dirsWithInsert ausführt für (var i = 0; i < dirsWithInsert.length; i++) { callHook$1(dirsWithInsert[i], 'eingefügt', vnode, alterVnode); } }; if (isCreate) { //Wenn es initialisiert ist mergeVNodeHook(vnode, 'insert', callInsert); //Dann rufe die Funktion mergeVNodeHook() auf } else { rufInsert(); } } if (dirsWithPostpatch.Länge) { mergeVNodeHook(vnode, 'postpatch', Funktion () { für (var i = 0; i < dirsWithPostpatch.length; i++) { callHook$1(dirsWithPostpatch[i], 'Komponente aktualisiert', vnode, alterVnode); } }); } wenn (!istErstellen) { für (Schlüssel in oldDirs) { wenn (!newDirs[Schlüssel]) { // nicht mehr vorhanden, Bindung aufheben callHook$1(alteDirs[Schlüssel], 'aufheben', alterV-Knoten, alterV-Knoten, isDestroy); } } } } Autor: Great Desert QQ: 22969969 Für die Bind-Hook-Funktion wird sie direkt ausgeführt, während für die eingefügte Hook-Funktion die Funktion im Array dirsWithInsert gespeichert und dann eine callInsert-Funktion definiert wird. Die Funktion greift über den Bereich auf die Variable dirsWithInsert zu und durchläuft die Variable, um nacheinander jede eingefügte Hook-Funktion auszuführen. Die Hook-Funktion mergeVNodeHook() speichert insert als Hook-Attribut in den entsprechenden Vnode-Daten. Wenn der Vnode in den übergeordneten Knoten eingefügt wird, werden die Hooks wie folgt aufgerufen: function mergeVNodeHook (def, hookKey, hook) { //Zeile 2074 führt die VNode-Hook-Funktion def zusammen: ein VNode hookKey: (Ereignisname, z. B.: insert) hook: Rückruffunktion if (def instanceof VNode) { //Wenn def ein VNode ist def = def.data.hook || (def.data.hook = {}); // setze es auf VNode.data.hook zurück. Wenn VNode.data.hook nicht existiert, initialisiere es mit einem leeren Objekt. Hinweis: VNode.data.hook existiert nicht für normale Knoten. } var-Aufrufer; var alterHook = def[hookKey]; Funktion wrappedHook () { hook.apply(this, arguments); //Führen Sie zuerst die Hook-Funktion aus // wichtig: Entfernen Sie den zusammengeführten Hook, um sicherzustellen, dass er nur einmal aufgerufen wird // und Speicherlecks verhindern remove(invoker.fns, wrappedHook); //Entferne dann wrappedHook aus invoker.fns, damit das Paket nur einmal ausgeführt wird} if (isUndef(oldHook)) { //Wenn oldHook nicht existiert, d. h., die HookKey-Hook-Funktion wurde zuvor nicht definiert // kein vorhandener Hook invoker = createFnInvoker([wrappedHook]); //Rufen Sie createFnInvoker() direkt auf, um eine Closure-Funktion zurückzugeben, deren Parameter die auszuführende Callback-Funktion ist} else { /* istanbul ignorieren wenn */ wenn (isDef(alterHook.fns) && isTrue(alterHook.merged)) { // bereits ein zusammengeführter Aufrufer invoker = alterHook; invoker.fns.push(wrappedHook); } anders { // bestehender einfacher Hook invoker = createFnInvoker([alterHook, verpackterHook]); } } invoker.merged = wahr; def[hookKey] = invoker; //Setze die hookKey-Eigenschaft von def so, dass sie auf den neuen Invoker verweist } createFnInvoker ist die Funktion, die der v-on-Anweisung entspricht. Sie verwendet dieselbe API. Nach der Ausführung fügen wir invoker wie folgt in den VNode.data.hook ein, der der Eingabe entspricht: Schließlich wird, nachdem der VNode in den übergeordneten Knoten eingefügt wurde, die Funktion invokeCreateHooks() ausgeführt. Diese Funktion durchläuft VNode.hook.insert und führt nacheinander jede Funktion aus. Außerdem führt sie unsere benutzerdefinierte eingefügte Hook-Funktion aus. ZusammenfassenDies ist das Ende dieses Artikels über benutzerdefinierte Anweisungen für die Vue.js-Quellcodeanalyse. Weitere relevante benutzerdefinierte Vue.js-Anweisungen finden Sie in früheren Artikeln auf 123WORDPRESS.COM oder in den folgenden verwandten Artikeln. Ich hoffe, dass jeder 123WORDPRESS.COM in Zukunft unterstützen wird! Das könnte Sie auch interessieren:
|
<<: Detaillierte Erläuterung der MySQL Master-Slave-Datenbankkonstruktionsmethode
>>: Verwenden von nginx + fastcgi zum Implementieren eines Bilderkennungsservers
Server-Abgleichlogik Wenn Nginx entscheidet, in w...
Inhaltsverzeichnis 1. Szenariobeschreibung: 2. Fa...
Ich frage mich, ob Sie wie ich ein Programmierer ...
Inhaltsverzeichnis Objekt.prototype.valueOf() Obj...
Als häufig verwendete Datenbank erfordert MySQL v...
In diesem Artikelbeispiel wird der spezifische Ja...
Dieser Hinweis ist ein Installationstutorial. Er ...
Inhaltsverzeichnis Einführung in Anaconda 1. Heru...
@Font-face grundlegende Einführung: @font-face ist...
Wenn Sie Ihr MySQL-Anmeldekennwort vergessen, ist...
Überprüfen Sie die Python-Version mit python -V. ...
Inhaltsverzeichnis 1. Schritte zum Download 2. Um...
Ab IE 8 wurde ein Kompatibilitätsmodus hinzugefügt...
Inhaltsverzeichnis Hintergrund Inspiration kommt ...
Lassen Sie mich zunächst über die allgemeine Idee...