# Événements personnalisés

Cette page suppose que vous avez déjà lu les Principes de base des composants. Lisez-le d'abord si vous n'êtes pas familier avec les composants.

# Noms d'événements

Comme les composants et les props, les noms d'événements fournissent une transformation automatique de la casse. Si vous émettez un événement à partir du composant enfant en camelCase, vous pourrez ajouter un écouteur en kebab-case dans le parent:

this.$emit('myEvent')
1
<my-component @my-event="doSomething"></my-component>
1

Comme pour la casse des props, nous vous recommandons d'utiliser des écouteurs d'événement en kebab-case lorsque vous utilisez des templates dans le DOM. Si vous utilisez des string templates, cette limitation ne s'applique pas.

# Définir des événements personalisés

Regardez une vidéo gratuite sur la façon de définir des événements personnalisés sur Vue School (EN)

Les événements émis peuvent être définis sur le composant via l'option emits.

app.component('custom-form', {
  emits: ['inFocus', 'submit']
})
1
2
3

Lorsqu'un événement natif (par exemple, click) est défini dans l'optionemits, l'événement du composant sera utilisé à la place d'un écouteur d'événements natif.

TIP

Il est recommandé de définir tous les événements émis afin de mieux documenter le fonctionnement d'un composant.

# Valider les événements émis

Semblable à la validation du type des props, un événement émis peut être validé s'il est défini avec la syntaxe Object au lieu de la syntaxe tableau.

Pour ajouter une validation, l'événement reçoit une fonction qui reçoit les arguments passés à l'appel $emit et retourne un booléen pour indiquer si l'événement est valide ou non.

app.component('custom-form', {
  emits: {
    // Pas de validation
    click: null,

    // Valider l'événement de soumission
    submit: ({ email, password }) => {
      if (email && password) {
        return true
      } else {
        console.warn('Invalid submit event payload!')
        return false
      }
    }
  },
  methods: {
    submitForm() {
      this.$emit('submit', { email, password })
    }
  }
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

# Arguments de `v-model

Par défaut, v-model sur un composant utilisemodelValue comme prop et update:modelValue comme événement. Nous pouvons modifier ces noms en passant un argument à v-model:

<my-component v-model:title="bookTitle"></my-component>
1

Dans ce cas, le composant enfant attendra un accessoire title et émettra l'événement update:title à synchroniser:

app.component('my-component', {
  props: {
    title: String
  },
  emits: ['update:title'],
  template: `
    <input
      type="text"
      :value="title"
      @input="$emit('update:title', $event.target.value)">
  `
})
1
2
3
4
5
6
7
8
9
10
11
12
<my-component v-model:title="bookTitle"></my-component>
1

# Liaisons multiples de v-model

En tirant parti de la possibilité de cibler une prop et un événement particulier comme nous l'avons appris auparavant avec les arguments de v-model, nous pouvons maintenant créer plusieurs liaisons v-model sur une seule instance de composant.

Chaque v-model sera synchronisé avec une prop différente, sans avoir besoin d'options supplémentaires dans le composant:

<user-name
  v-model:first-name="firstName"
  v-model:last-name="lastName"
></user-name>
1
2
3
4
app.component('user-name', {
  props: {
    firstName: String,
    lastName: String
  },
  emits: ['update:firstName', 'update:lastName'],
  template: `
    <input
      type="text"
      :value="firstName"
      @input="$emit('update:firstName', $event.target.value)">

    <input
      type="text"
      :value="lastName"
      @input="$emit('update:lastName', $event.target.value)">
  `
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

See the Pen Multiple v-models by Vue (@Vue) on CodePen.

# Gestion des modificateurs de v-model

Lorsque nous avons appris les liaisons d'entrée de formulaire, nous avons vu que v-model avait des modificateurs intégrés - .trim, .number et .lazy. Dans certains cas, cependant, vous pouvez également ajouter vos propres modificateurs personnalisés.

Créons un exemple de modificateur personnalisé, capitalize, qui met en majuscule la première lettre de la chaîne de caractère fournie par la liaison v-model.

Les modificateurs ajoutés à un composant v-model seront fournis au composant via la prop modelModifiers. Dans l'exemple ci-dessous, nous avons créé un composant qui contient un accessoire modelModifiers qui par défaut est un objet vide.

Notez que lorsque le hook de cycle de vie created du composant se déclenche, la prop modelModifiers contient capitalize et sa valeur est true - car il est défini sur la liaison v-model v-model.capitalize="myText".

<my-component v-model.capitalize="myText"></my-component>
1
app.component('my-component', {
  props: {
    modelValue: String,
    modelModifiers: {
      default: () => ({})
    }
  },
  emits: ['update:modelValue'],
  template: `
    <input type="text"
      :value="modelValue"
      @input="$emit('update:modelValue', $event.target.value)">
  `,
  created() {
    console.log(this.modelModifiers) // { capitalize: true }
  }
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

Maintenant que nous avons configuré notre prop, nous pouvons vérifier les clés d'objet modelModifiers et écrire un gestionnaire pour changer la valeur émise. Dans le code ci-dessous, nous mettrons en majuscule la chaîne chaque fois que l'élément <input/> déclenche un événement input.

<div id="app">
  <my-component v-model.capitalize="myText"></my-component>
  {{ myText }}
</div>
1
2
3
4
const app = Vue.createApp({
  data() {
    return {
      myText: ''
    }
  }
})

app.component('my-component', {
  props: {
    modelValue: String,
    modelModifiers: {
      default: () => ({})
    }
  },
  emits: ['update:modelValue'],
  methods: {
    emitValue(e) {
      let value = e.target.value
      if (this.modelModifiers.capitalize) {
        value = value.charAt(0).toUpperCase() + value.slice(1)
      }
      this.$emit('update:modelValue', value)
    }
  },
  template: `<input
    type="text"
    :value="modelValue"
    @input="emitValue">`
})

app.mount('#app')
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

Pour les liaisons v-model avec arguments, le nom de prop généré seraarg + "Modifiers":

<my-component v-model:description.capitalize="myText"></my-component>
1
app.component('my-component', {
  props: ['description', 'descriptionModifiers'],
  emits: ['update:description'],
  template: `
    <input type="text"
      :value="description"
      @input="$emit('update:description', $event.target.value)">
  `,
  created() {
    console.log(this.descriptionModifiers) // { capitalize: true }
  }
})
1
2
3
4
5
6
7
8
9
10
11
12

Deployed on Netlify.
Dernière Mise-à-jour: 3/19/2021, 8:08:18 PM