Die Macht von benutzerdefinierten Direktiven in Vue

Avatar of Sarah Drasner
Sarah Drasner am

DigitalOcean bietet Cloud-Produkte für jede Phase Ihrer Reise. Starten Sie mit 200 $ kostenlosem Guthaben!

Wenn Sie gerade erst lernen, ein JavaScript-Framework zu beherrschen, fühlt es sich ein wenig an wie ein Kind im Süßigkeitenladen. Sie nehmen alles auf, was Ihnen zur Verfügung steht, und schon zu Beginn gibt es Dinge, die Ihnen das Leben als Entwickler erleichtern. Unvermeidlich erreichen wir jedoch alle einen Punkt in der Arbeit mit einem Framework, an dem wir einen Anwendungsfall haben, den das Framework nicht sehr gut abdeckt.

Das Schöne an Vue ist, dass es unglaublich funktionsreich ist. Aber selbst wenn Sie einen Sonderfall haben, der nicht vom Framework abgedeckt wird, sind Sie auch dort abgesichert, da Sie ganz einfach eine benutzerdefinierte Direktive erstellen können.

Was sind Direktiven?

Ich habe einen Beitrag hier über Direktiven in meinem Leitfaden zu Vue.js geschrieben, aber lassen Sie uns eine Auffrischung machen.

Direktiven sind winzige Befehle, die Sie an DOM-Elemente anhängen können. Sie sind mit v- präfixiert, um die Bibliothek wissen zu lassen, dass Sie eine spezielle Markup-Art verwenden, und um die Syntax konsistent zu halten. Sie sind typischerweise nützlich, wenn Sie einen Low-Level-Zugriff auf ein HTML-Element benötigen, um ein Verhalten zu steuern.

Einige Direktiven, mit denen Sie vielleicht schon vertraut sind, wenn Sie mit Vue (oder Angular, was das angeht) gearbeitet haben, sind v-if, v-else, v-show usw. Wir werden auf einige Grundlagen eingehen, aber wenn Sie lieber die Beispiele durchlesen möchten, können Sie ein wenig weiter unten auf der Seite scrollen und wahrscheinlich immer noch die Konzepte verstehen.

Hier sind einige Möglichkeiten, eine Direktive zu verwenden, zusammen mit einem Gegenbeispiel. Diese Beispiele sind nicht vorschreibend, sondern einfach Anwendungsfälle. Das Wort Beispiel steht hier anstelle der tatsächlichen Direktive.

v-example – dies instanziiert eine Direktive, akzeptiert aber keine Argumente. Ohne die Übergabe eines Wertes wäre dies nicht sehr flexibel, aber Sie könnten trotzdem ein Stück Funktionalität an das DOM-Element hängen.

v-example="value" – dies übergibt einen Wert an die Direktive, und die Direktive ermittelt, was basierend auf diesem Wert zu tun ist.

<div v-if="stateExample">I will show up if stateExample is true</div>

v-example="'string'" – dies erlaubt Ihnen die Verwendung eines Strings als Ausdruck.

<p v-html="'<strong>this is an example of a string in some text</strong>'"></p>

v-example:arg="value" – dies erlaubt uns, ein Argument an die Direktive zu übergeben. Im folgenden Beispiel binden wir an eine Klasse, und wir würden sie mit einem separat gespeicherten Objekt stylen.

<div v-bind:class="someClassObject"></div>

v-example:arg.modifier="value" – dies erlaubt uns die Verwendung eines Modifikators. Das folgende Beispiel erlaubt uns, preventDefault() bei einem Klickereignis aufzurufen.

<button v-on:submit.prevent="onSubmit"></button>

Verständnis von benutzerdefinierten Direktiven

Nachdem wir nun alle Möglichkeiten der Verwendung von Direktiven gesehen haben, lassen Sie uns aufschlüsseln, wie wir sie mit einer *benutzerdefinierten* Direktive implementieren würden, die wir selbst erstellen. Ein gutes Beispiel für etwas, wofür Sie eine benutzerdefinierte Direktive verwenden könnten, ist ein scroll-Ereignis, also sehen wir uns an, wie wir das schreiben würden.

Ganz grundlegend würden wir so eine globale Direktive erstellen. (Aber sie tut noch nichts!) – sie erstellt nur die Direktive.

Vue.directive('tack');

Am Element selbst würde es so aussehen

<p v-tack>This element has a directive on it</p>

Es gibt mehrere Hooks, die uns zur Verfügung stehen, und jeder von ihnen hat die Option auf einige Argumente. Die Hooks sind wie folgt:

  • bind – Dies geschieht, sobald die Direktive an das Element angehängt ist.
  • inserted – Dieser Hook tritt auf, sobald das Element in den übergeordneten DOM eingefügt wurde.
  • update – Dieser Hook wird aufgerufen, wenn sich das Element aktualisiert, aber die Kinder noch nicht aktualisiert wurden.
  • componentUpdated – Dieser Hook wird aufgerufen, sobald die Komponente *und* die Kinder aktualisiert wurden.
  • unbind – Dieser Hook wird aufgerufen, sobald die Direktive entfernt wird.
directives hooks diagram

Persönlich finde ich bind und update die nützlichsten der fünf.

Jeder dieser Hooks hat die Argumente el, binding und vnode zur Verfügung, mit Ausnahme von update und componentUpdated, die auch oldVnode exponieren, um zwischen dem älteren übergebenen Wert und dem neueren Wert zu unterscheiden.

el ist, wie Sie vielleicht erwarten, das Element, auf dem die Bindung sitzt. binding ist ein Objekt, das Argumente enthält, die an die Hooks übergeben werden. Es gibt viele verfügbare Argumente, darunter name, value, oldValue, expression, arg und modifiers. vnode hat einen ungewöhnlicheren Anwendungsfall, es ist verfügbar, falls Sie direkt auf den Knoten im virtuellen DOM verweisen müssen. Sowohl binding als auch vnode sollten als schreibgeschützt behandelt werden.

Eine benutzerdefinierte Direktive erstellen

Nachdem wir das aufgeschlüsselt haben, können wir uns ansehen, wie wir eine benutzerdefinierte Direktive in Aktion verwenden würden. Lassen Sie uns auf dem ersten Beispiel aufbauen, das wir gerade behandelt haben, um es nützlicher zu machen

Vue.directive('tack', {
 bind(el, binding, vnode) {
    el.style.position = 'fixed'
  }
});

Und auf dem HTML selbst

<p v-tack>I will now be tacked onto the page</p>

Das ist in Ordnung, aber es ist nicht sehr flexibel, bis wir einen Wert übergeben und ihn aktualisieren oder ihn im laufenden Betrieb wiederverwenden. Lassen Sie uns entscheiden, wie weit vom oberen Rand wir das Element fixieren möchten

Vue.directive('tack', {
  bind(el, binding, vnode) {
    el.style.position = 'fixed'
    el.style.top = binding.value + 'px'
  }
});
<div id="app">
  <p>Scroll down the page</p>
  <p v-tack="70">Stick me 70px from the top of the page</p>
</div>

Siehe den Stift.

Nehmen wir an, ich wollte jetzt zwischen der Tatsache unterscheiden, ob wir die 70px vom oberen oder vom linken Rand aus versetzen. Das könnten wir tun, indem wir ein Argument übergeben

<p v-tack:left="70">I'll now be offset from the left instead of the top</p>
Vue.directive('tack', {
  bind(el, binding, vnode) {
    el.style.position = 'fixed';
    const s = (binding.arg == 'left' ? 'left' : 'top');
    el.style[s] = binding.value + 'px';
  }
});

Siehe den Stift.

Sie können auch mehr als einen Wert verwenden. Das könnten Sie auf die gleiche Weise tun, wie Sie es für reguläre Direktiven tun würden

<p v-tack="{ top: '40', left: '100' }">Stick me 40px from the top of the page and 100px from the left of the page</p>

Und dann würde die Direktive neu geschrieben, um mit beiden zu arbeiten

Vue.directive('tack', {
  bind(el, binding, vnode) {
    el.style.position = 'fixed';
    el.style.top = binding.value.top + 'px';
    el.style.left = binding.value.left + 'px';
  }
}); 

Siehe den Stift.

Wir können auch etwas Komplexeres schreiben, bei dem wir Methoden basierend auf unseren benutzerdefinierten Direktiven erstellen und modifizieren können. Hier machen wir ein Waypoints-ähnliches Beispiel, bei dem wir eine Animation erstellen können, die bei einem bestimmten Scroll-Ereignis mit wenig Code ausgelöst wird

Vue.directive('scroll', {
  inserted: function(el, binding) {
    let f = function(evt) {
      if (binding.value(evt, el)) {
        window.removeEventListener('scroll', f);
      }
    };
    window.addEventListener('scroll', f);
  },
});

// main app
new Vue({
  el: '#app',
  methods: {
   handleScroll: function(evt, el) {
    if (window.scrollY > 50) {
      TweenMax.to(el, 1.5, {
        y: -10,
        opacity: 1,
        ease: Sine.easeOut
      })
    }
    return window.scrollY > 100;
    }
  }
});
<div class="box" v-scroll="handleScroll">
  <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. A atque amet harum aut ab veritatis earum porro praesentium ut corporis. Quasi provident dolorem officia iure fugiat, eius mollitia sequi quisquam.</p>
</div>

Siehe den Stift.

In diesen Pens halten wir alles einfach, damit Sie es leicht sehen können. In einer echten App können Sie wirklich schöne, benutzerdefinierte und flexible Direktiven erstellen, die Ihrem gesamten Team zur Verfügung stehen.

In einem tatsächlichen Build-Prozess würde ich den Direktiven-Code in die Datei `main.js` legen, die sich im Stammverzeichnis des `src`-Verzeichnisses befindet (wenn Sie etwas wie den Vue-cli-Build verwenden), sodass `App.vue` und alle nachfolgenden .vue-Dateien im Komponentenverzeichnis darauf zugreifen können. Es gibt auch andere Möglichkeiten, damit zu arbeiten, aber ich habe festgestellt, dass dies die flexibelste Implementierung für die gesamte App ist.

Wenn Sie mehr über das Vue-Framework erfahren möchten, schauen Sie sich unseren Leitfaden an.