Benutzerdefinierte Ereignisse


Auf dieser Seite wird davon ausgegangen, dass Sie Komponentengrundlagen gelesen haben. Wenn Sie noch nicht viel über Komponenten wissen, empfehle ich Ihnen, es zuerst zu lesen.


Inhaltsverzeichnis


Ereignisname


ist unterschiedlich Für Komponenten und Requisiten gibt es keine automatische Groß-/Kleinschreibung für Ereignisnamen. Stattdessen muss der Name des ausgelösten Ereignisses genau mit dem Namen übereinstimmen, der zum Abhören dieses Ereignisses verwendet wird. Wenn beispielsweise ein Ereignis mit einem CamelCase-Namen ausgelöst wird:

this.$emit('myEvent')

, hat das Anhören der Kebab-Case-Version dieses Namens keine Auswirkung:

<!-- 没有效果 -->
<my-component v-on:my-event="doSomething"></my-component>

Im Gegensatz zu Komponenten und Requisiten, Ereignissen Der Name wird nicht als JavaScript-Variable oder Eigenschaftsname verwendet, daher gibt es keinen Grund, camelCase oder PascalCase zu verwenden. Und der v-on-Ereignis-Listener wird in der DOM-Vorlage automatisch in Kleinbuchstaben konvertiert (da bei HTML die Groß-/Kleinschreibung nicht beachtet wird), sodass v-on:myEvent zu v-on:myevent wird – was es unmöglich macht, dass myEvent überwacht ankommt.

Daher empfehlen wir Ihnen immer kebab-caseEreignisnamen zu verwenden.


Benutzerdefinierte Komponente v-model


2.2.0 Hinzugefügt

Das v-model einer Komponente verwendet standardmäßig den Namen value prop und benannt input Ereignisse, aber Eingabesteuerelemente wie Optionsfelder, Kontrollkästchen usw. können das value-Attribut für verschiedene Zwecke verwenden. Die Option model kann verwendet werden, um solche Konflikte zu vermeiden:

Vue.component('base-checkbox', {
  model: {
    prop: 'checked',
    event: 'change'
  },
  props: {
    checked: Boolean
  },
  template: `
    <input
      type="checkbox"
      v-bind:checked="checked"
      v-on:change="$emit('change', $event.target.checked)"
    >
  `
})

Wenn Sie nun v-model für diese Komponente verwenden:

<base-checkbox v-model="lovingVue"></base-checkbox>

Der Wert von lovingVue wird hier an dieses A übergeben Requisite mit dem Namen checked. Wenn <base-checkbox> gleichzeitig ein change-Ereignis mit einem neuen Wert auslöst, werden die Attribute dieses lovingVue aktualisiert.

Beachten Sie, dass Sie die props-Requisite weiterhin in den checked-Optionen der Komponente deklarieren müssen.


Native Ereignisse an Komponenten binden


Dieses Mal haben Sie möglicherweise viele Ich möchte ein natives Ereignis direkt im Stammelement einer Komponente abhören. Zu diesem Zeitpunkt können Sie den Modifikator v-on von .native verwenden:

<base-input v-on:focus.native="onFocus"></base-input>

Das kann manchmal nützlich sein, ist aber keine gute Idee, wenn Sie versuchen, auf ein ganz bestimmtes Element wie <input> zu achten. Beispielsweise wurde die obige <base-input>-Komponente möglicherweise wie folgt umgestaltet, sodass das Stammelement tatsächlich ein <label>-Element ist:

<label>
  {{ label }}
  <input
    v-bind="$attrs"
    v-bind:value="value"
    v-on:input="$emit('input', $event.target.value)"
  >
</label>

Zu diesem Zeitpunkt schlägt der .native-Listener des übergeordneten Elements stillschweigend fehl. Es werden keine Fehler generiert, aber der onFocus-Handler wird nicht wie erwartet aufgerufen.

Um dieses Problem zu lösen, stellt Vue ein $listeners-Attribut bereit, bei dem es sich um ein Objekt handelt, das alle Listener enthält, die auf diese Komponente agieren. Beispiel:

{
  focus: function (event) { /* ... */ }
  input: function (value) { /* ... */ },
}

Mit diesem $listeners-Attribut können Sie v-on="$listeners" verwenden, um alle Ereignis-Listener auf ein bestimmtes untergeordnetes Element dieser Komponente zu verweisen. Für Komponenten wie <input>, mit denen Sie auch v-model arbeiten möchten, ist es oft nützlich, eine berechnete Eigenschaft für diese Listener wie die folgende zu erstellen inputListeners:

Vue.component('base-input', {
  inheritAttrs: false,
  props: ['label', 'value'],
  computed: {
    inputListeners: function () {
      var vm = this
      // `Object.assign` 将所有的对象合并为一个新对象
      return Object.assign({},
        // 我们从父级添加所有的监听器
        this.$listeners,
        // 然后我们添加自定义监听器,
        // 或覆写一些监听器的行为
        {
          // 这里确保组件配合 `v-model` 的工作
          input: function (event) {
            vm.$emit('input', event.target.value)
          }
        }
      )
    }
  },
  template: `
    <label>
      {{ label }}
      <input
        v-bind="$attrs"
        v-bind:value="value"
        v-on="inputListeners"
      >
    </label>
  `
})

Jetzt ist die <base-input>-Komponente vorhanden eine völlig transparente Hülle, was bedeutet, dass sie sich genau wie eine gewöhnliche <input> verhalten kann Das Element wird auf die gleiche Weise verwendet: Es funktionieren dieselben Eigenschaften und Listener.


.sync.sync

Modifikatoren

2.3.0 Neu hinzugefügt

update:myPropNameIn einigen Fällen müssen wir möglicherweise eine Requisite „in beide Richtungen binden“. Sicherlich". Leider führt eine echte bidirektionale Bindung zu Wartungsproblemen, da untergeordnete Komponenten ihre übergeordneten Komponenten ändern können, ohne dass eine offensichtliche Änderungsquelle für die übergeordneten oder untergeordneten Komponenten vorliegt. title

Aus diesem Grund empfehlen wir, stattdessen den

-Modus zum Auslösen von Ereignissen zu verwenden. Beispielsweise können wir in einer hypothetischen Komponente, die eine

-Requisite enthält, die Absicht ausdrücken, ihr einen neuen Wert zuzuweisen mit:

this.$emit('update:title', newTitle)
.syncDann kann die übergeordnete Komponente dieses Ereignis abhören und bei Bedarf aktualisieren Lokale Datenattribute. Zum Beispiel:

<text-document
  v-bind:title="doc.title"
  v-on:update:title="doc.title = $event"
></text-document>
Der Einfachheit halber stellen wir für dieses Muster eine Abkürzung bereit, nämlich

Modifikatoren: .sync

<text-document v-bind:title.sync="doc.title"></text-document>
v-bindBeachten Sie, dass v-bind:title.sync=”doc.title   ‘!’ mit dem Modifikator v-model nicht zusammen mit

und Ausdrücken (z. B. <🎜) verwendet werden kann >" ist ungültig. Stattdessen können Sie nur den Eigenschaftsnamen angeben, den Sie binden möchten, ähnlich wie
.

.sync v-bindWenn wir ein Objekt verwenden, um mehrere festzulegen prop, Sie können diesen

-Modifikator auch mit <🎜> verwenden: <🎜>
<text-document v-bind.sync="doc"></text-document>

Dadurch wird jedes Attribut (z. B. Titel) im Dokumentobjekt als unabhängige Requisite übergeben und dann V-On-Listener für Aktualisierungen hinzugefügt.

Die Verwendung von v-bind.sync für ein Literalobjekt wie v-bind.sync=”{ title: doc.title }” funktioniert nicht ordnungsgemäß, da beim Parsen eines komplexen Ausdrucks wie diesem viele Randfälle berücksichtigt werden müssen.