Skip to content

Benutzerdefinierte Direktiven

Einführung

Zusätzlich zu den Standard-Direktiven, die im Kern ausgeliefert werden (wie v-model oder v-show), erlaubt es Vue auch, eigene Direktiven zu registrieren.

Wir haben zwei Formen der Wiederverwendung von Code in Vue eingeführt: components und composables. Komponenten sind die Hauptbausteine, während Composables sich auf die Wiederverwendung von zustandsbehafteter Logik konzentrieren. Benutzerdefinierte Direktiven hingegen sind hauptsächlich für die Wiederverwendung von Logik gedacht, die einen Low-Level-DOM-Zugriff auf einfache Elemente beinhaltet.

Eine benutzerdefinierte Richtlinie ist als Objekt definiert, das Lebenszyklus-Hooks enthält, die denen einer Komponente ähneln. Die Hooks erhalten das Element, an das die Direktive gebunden ist. Hier ist ein Beispiel für eine Direktive, die eine Eingabe fokussiert, wenn das Element in das DOM von Vue eingefügt wird:

vue
<script setup>
// enables v-focus in templates
const vFocus = {
  mounted: (el) => el.focus()
}
</script>

<template>
  <input v-focus />
</template>
js
const focus = {
  mounted: (el) => el.focus()
}

export default {
  directives: {
    // enables v-focus in template
    focus
  }
}
template
<input v-focus />

Angenommen, Sie haben nicht an anderer Stelle auf der Seite geklickt, sollte die obige Eingabe automatisch fokussiert werden. Diese Direktive ist nützlicher als das autofocus-Attribut, weil sie nicht nur beim Laden der Seite funktioniert - sie funktioniert auch, wenn das Element dynamisch von Vue eingefügt wird.

In <script setup> kann jede camelCase-Variable, die mit dem Präfix v beginnt, als eigene Direktive verwendet werden. Im obigen Beispiel kann „vFocus“ in der Vorlage als „v-focus“ verwendet werden.

Wenn <script setup> nicht verwendet wird, können benutzerdefinierte Anweisungen mit der Option directives registriert werden:

js
export default {
  setup() {
    /*...*/
  },
  directives: {
    // enables v-focus in template
    focus: {
      /* ... */
    }
  }
}

Ähnlich wie Komponenten müssen benutzerdefinierte Direktiven registriert werden, damit sie in Vorlagen verwendet werden können. Im obigen Beispiel verwenden wir die lokale Registrierung über die Option Direktiven.

Es ist auch üblich, benutzerdefinierte Anweisungen global auf App-Ebene zu registrieren:

js
const app = createApp({})

// make v-focus usable in all components
app.directive('focus', {
  /* ... */
})

TIP

Benutzerdefinierte Direktiven sollten nur verwendet werden, wenn die gewünschte Funktionalität nur durch direkte DOM-Manipulation erreicht werden kann. Bevorzugen Sie nach Möglichkeit deklaratives Template-Design mit integrierten Direktiven wie „v-bind“, da diese effizienter und serverfreundlicher sind.

Direktive Hooks

Ein Direktivendefinitionsobjekt kann mehrere Hook-Funktionen bereitstellen (alle optional):

js
const myDirective = {
  // called before bound element's attributes
  // or event listeners are applied
  created(el, binding, vnode, prevVnode) {
    // see below for details on arguments
  },
  // called right before the element is inserted into the DOM.
  beforeMount(el, binding, vnode, prevVnode) {},
  // called when the bound element's parent component
  // and all its children are mounted.
  mounted(el, binding, vnode, prevVnode) {},
  // called before the parent component is updated
  beforeUpdate(el, binding, vnode, prevVnode) {},
  // called after the parent component and
  // all of its children have updated
  updated(el, binding, vnode, prevVnode) {},
  // called before the parent component is unmounted
  beforeUnmount(el, binding, vnode, prevVnode) {},
  // called when the parent component is unmounted
  unmounted(el, binding, vnode, prevVnode) {}
}

Hook-Argumente

An Direktiven-Hooks werden diese Argumente übergeben:

  • el: das Element, an das die Direktive gebunden ist. Dies kann verwendet werden, um das DOM direkt zu manipulieren.

  • binding: ein Objekt mit den folgenden Eigenschaften.

    • value: Der an die Direktive übergebene Wert. Beispielsweise wäre in v-my-directive="1 + 1" der Wert 2.
    • oldValue: Der vorherige Wert, nur in beforeUpdate und „updated“ verfügbar. Er ist verfügbar, unabhängig davon, ob sich der Wert geändert hat oder nicht.
    • arg: Das an die Direktive übergebene Argument, sofern vorhanden. Beispielsweise wäre in v-my-directive:foo das Argument "foo".
    • modifiers: Ein Objekt, das Modifikatoren enthält, falls vorhanden. Beispielsweise wäre in v-my-directive.foo.bar das Modifikatorobjekt { foo: true, bar: true }.
    • instance: Die Instanz der Komponente, in der die Direktive verwendet wird.
    • dir: das Direktivendefinitionsobjekt.
  • vnode: der zugrunde liegende VNode, der das gebundene Element darstellt.

  • prevNode: Der VNode, der das gebundene Element aus dem vorherigen Render darstellt. Nur in den Hooks beforeUpdate und updated verfügbar.

Betrachten Sie als Beispiel die folgende Verwendung der Direktive:

template
<div v-example:foo.bar="baz">

Das Argument „Bindung“ wäre ein Objekt in der Form:

js
{
  arg: 'foo',
  modifiers: { bar: true },
  value: /* value of `baz` */,
  oldValue: /* value of `baz` from previous update */
}

Ähnlich wie integrierte Direktiven können benutzerdefinierte Direktivenargumente dynamisch sein. Beispiel:

template
<div v-example:[arg]="value"></div>

Hier wird das Direktiveargument basierend auf der Eigenschaft „arg“ in unserem Komponentenstatus reaktiv aktualisiert.

Note

Mit Ausnahme von el sollten Sie diese Argumente als schreibgeschützt behandeln und niemals ändern. Wenn Sie Informationen über Hooks hinweg austauschen müssen, wird empfohlen, dies über den Datensatz des Elements zu tun.

Funktionskürzel

Es ist üblich, dass eine benutzerdefinierte Direktive für „mounted“ und „updated“ dasselbe Verhalten aufweist, ohne dass die anderen Hooks erforderlich sind. In solchen Fällen können wir die Direktive als Funktion definieren:

template
<div v-color="color"></div>
js
app.directive('color', (el, binding) => {
  // this will be called for both `mounted` and `updated`
  el.style.color = binding.value
})

Objektliterale

If your directive needs multiple values, you can also pass in a JavaScript object literal. Remember, directives can take any valid JavaScript expression.

template
<div v-demo="{ color: 'white', text: 'hello!' }"></div>
js
app.directive('demo', (el, binding) => {
  console.log(binding.value.color) // => "white"
  console.log(binding.value.text) // => "hello!"
})

Usage on Components

When used on components, custom directives will always apply to a component's root node, similar to Fallthrough Attributes.

template
<MyComponent v-demo="test" />
template
<!-- template of MyComponent -->

<div> <!-- v-demo directive will be applied here -->
  <span>My component content</span>
</div>

Note that components can potentially have more than one root node. When applied to a multi-root component, a directive will be ignored and a warning will be thrown. Unlike attributes, directives can't be passed to a different element with v-bind="$attrs". In general, it is not recommended to use custom directives on components.

Benutzerdefinierte Direktiven has loaded