VueJS: Why Trigger 'Input' Event Within 'Input' Event Handler?

Viewed 16097

I'm learning VueJS. I'm figuring out their currency validation example 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))
    }
  }
})

The $emit call at the bottom of the updateValue function, triggers an input event.

When I comment it out, the real time currency validation no longer works. So I realize it has a purpose.

But why trigger an input event inside an input event?

You'd think the input event would fire again, causing the updateValue handler to fire again, causing a stack overflow due to recursive calls.

I understand VueJS's much simpler $emit example code. It's just like Jquery's trigger function.

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

But in the currency validation example, I do not understand why $emit is used the way it's used, and why it works the way it works.

Can somebody explain?

1 Answers
Related