web-dev-qa-db-fra.com

VueJS: Pourquoi déclencher l'événement «Input» dans le gestionnaire d'événements «Input»?

J'apprends VueJS. Je trouve leur validation de devise exemple de code .

Vue.component('currency-input', {
  template: `
    <span>
      $
      <input
        ref="input"
        v-bind:value="value"
        v-on:input="updateValue($event.target.value)">
    </span>
  `,
  props: ['value'],
  methods: {
    // Instead of updating the value directly, this
    // method is used to format and place constraints
    // on the input's value
    updateValue: function (value) {
      var formattedValue = value
        // Remove whitespace on either side
        .trim()
        // Shorten to 2 decimal places
        .slice(
          0,
          value.indexOf('.') === -1
            ? value.length
            : value.indexOf('.') + 3
        )
      // If the value was not already normalized,
      // manually override it to conform
      if (formattedValue !== value) {
        this.$refs.input.value = formattedValue
      }
      // Emit the number value through the input event
      this.$emit('input', Number(formattedValue))
    }
  }
})

L'appel $ emit au bas de la fonction updateValue, déclenche un événement d'entrée.

Lorsque je le commente, la validation de la devise en temps réel ne fonctionne plus. Je me rends donc compte que cela a un but.

Mais pourquoi déclencher un événement d'entrée dans un événement d'entrée?

Vous penseriez que l'événement d'entrée se déclencherait à nouveau, provoquant le déclenchement du gestionnaire updateValue, provoquant un débordement de pile en raison d'appels récursifs.

Je comprends l'exemple de code $ emit beaucoup plus simple de VueJS. C'est comme la fonction de déclenchement de Jquery.

vm.$on('test', function (msg) {
  console.log(msg)
})
vm.$emit('test', 'hi')
// -> "hi"

Mais dans l'exemple de validation de devise, je ne comprends pas pourquoi $ emit est utilisé de la façon dont il est utilisé, et pourquoi il fonctionne de la façon dont il fonctionne.

Quelqu'un peut-il expliquer?

9
Jay

L'appel Emit ici vous permet de vous connecter à l'événement dans des contextes parents. L'événement Input est également utilisé par la directive v-model Pour gérer la liaison bidirectionnelle avec les composants.

v-model='model' Est essentiellement v-bind:value='model' v-on:input='model = $event.target.value' Avec quelques bits ajoutés pour le faire jouer Nice. Lorsque vous supprimez la this.$emit('input', Number(formattedValue)) vous supprimez le mécanisme qui met à jour la valeur en dehors du composant.

EDIT: @Jay attention à ce que vous souhaitez parfois

Tous les éléments en HTML ont une série de gestionnaires natifs pour les événements courants; redimensionner, charger, décharger, etc. Ceux-ci gèrent ce qu'il faut faire lorsque la page change de rendu et peuvent être désactivés ou ajoutés, car l'introduction des navigateurs JavaScript a utilisé un système de pompe d'événements qui permet d'attacher plusieurs fonctions à tout événement qui exécuter en séquence lorsque l'événement est déclenché. Un exemple étant comment vous pouvez exécuter 3 fonctions sur redimensionner pour gérer les cas Edge tels que la taille minimale/maximale, l'orientation de l'écran, etc.

Les éléments de formulaire implémentent généralement leurs propres fonctions d'événement de base: keydown, keyup, mousedown, mouseup. Ces fonctions de base invoquent des événements pour nous faciliter la vie en tant que développeurs, à savoir: saisie, flou, concentration. Certains ont des événements spécialisés comme dans les éléments sélectionnés implémentant le changement, les balises de formulaire implémentant soumettre.

Les balises d'entrée sur le focus capturent la saisie au clavier et affichent le curseur de saisie de texte pour indiquer qu'il est prêt à recevoir la saisie. Il ajoute des gestionnaires pour le code de touche de tabulation qui trouve la prochaine entrée disponible et déplace le focus sur cet élément. Le système de fonction de style de pompe d'événement est idéal ici car il vous permet de vous lier à la mise au point et de faire des choses comme changer la couleur d'arrière-plan ou la bordure lorsque l'entrée est mise au point sans avoir à implémenter le code pour capturer l'entrée ou afficher le curseur vous-même.

Les balises d'entrée déclenchent également l'événement input lorsque vous les saisissez, indiquant que l'entrée a changé, indiquant au navigateur de modifier la valeur et de mettre à jour l'affichage afin que la fonctionnalité attendue par l'utilisateur soit cohérente.

Dans l'exemple currency-input, Nous ajoutons la fonction updateValue pour travailler avec la fonction native et traiter la valeur d'entrée de l'événement, dans la fonction updateValue nous modifions la représentation sous forme de chaîne de la valeur et besoin d'un endroit pour le mettre. Vous pouvez simplement ajouter une propriété de données pour contenir la valeur et lier la propriété de valeur d'entrée à la propriété de données permettant au currency-input De gérer en interne l'affichage du résultat, mais cela verrouillerait la valeur derrière un accesseur privé et vous le feriez être incapable de modifier ou de récupérer la valeur de la valeur formatée en devise résultante.

En utilisant this.$emit('input', Number(formattedValue)), la fonction updateValue agit de manière similaire à la balise native input en générant un événement qui peut être capturé par le contexte parent et utilisé. Vous pouvez le stocker dans une valeur, l'utiliser comme base pour une fonction, ou même l'ignorer complètement, même si cela n'aide pas beaucoup. Cela vous permet de garder une trace de la valeur de l'entrée et de la modifier selon vos besoins ou de l'envoyer au serveur, de l'afficher, etc.

Il est également lié à quelques directives les plus pertinentes v-model Qui est du sucre syntaxique pour permettre une liaison de propriété value et une liaison d'événement input à une propriété de données dans le contexte actuel. En fournissant un accessoire value et en émettant un événement input, un élément personnalisé peut agir de manière similaire à un élément de formulaire natif dans les systèmes d'une application Vue. Une extrêmement fonctionnalité intéressante lorsque vous souhaitez emballer et distribuer ou réutiliser des composants.

C'est beaucoup plus agréable d'aller:

...
<currency-input v-model='dollarValue'></currency-input>
<input v-model='dollarValue'>
...

Que d'avoir à ajouter des liaisons value et input partout ergo:

...
<currency-input v-bind:value='dollarValue' v-on:input='updateDollarValue($event.target.value)'></currency-input>
<input v-bind:value='dollarValue' v-on:input='updateDollarValue($event.target.value)'>
...

Maintenant que ma bizarre randonnée est terminée, j'espère que cela a aidé à comprendre certains des motifs et du raisonnement derrière l'exemple currency-input.

11
Justin MacArthur