VueJS:为什么在 'Input' 事件处理程序中触发 'Input' 事件?

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

我正在学习 VueJS。我正在计算他们的货币验证 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))
    }
  }
})

updateValue 函数底部的 $emit 调用,触发输入事件。

当我将其注释掉时,实时货币验证不再有效。所以我意识到它是有目的的。

但为什么要在输入事件中触发输入事件?

您认为输入事件会再次触发,导致 updateValue 处理程序再次触发,从而导致递归调用导致堆栈溢出。

我理解 VueJS 更简单的 $emit 示例代码。就像Jquery的触发函数一样。

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

但在货币验证示例中,我不明白为什么 $emit 是这样使用的,为什么它会这样工作。

有人可以解释一下吗?

此处的 Emit 调用是为了让您可以挂接到父上下文中的事件。 v-model 指令也使用 Input 事件来处理与组件的双向绑定。

v-model='model' 本质上是 v-bind:value='model' v-on:input='model = $event.target.value' 添加了一些位以使其播放效果更好。当您删除 this.$emit('input', Number(formattedValue)) 时,您将删除更新组件外部值的机制。

编辑:@Jay 小心你有时想要什么

HTML 中的所有元素都有一系列用于常见事件的本机处理程序;调整大小、加载、卸载等。这些处理页面更改呈现时要执行的操作,并且可以禁用或添加,因为 JavaScript 浏览器的引入使用了允许附加多个功能的事件泵系统引发事件时按顺序 运行 的任何事件。一个例子是如何在调整大小时使用 3 个函数 运行 来处理边缘情况,例如 minimum/maximum 大小、屏幕方向等

表单元素通常实现自己的基本事件函数:keydown、keyup、mousedown、mouseup。这些基本功能调用事件使我们作为开发人员的生活更轻松,它们是:输入、模糊、焦点。有些有专门的事件,例如 select 元素实现更改,表单标签实现提交。

焦点上的输入标签捕获键盘输入并显示文本输入光标以指示它已准备好接收输入。它添加了用于查找下一个可用输入并将焦点转移到该元素的选项卡键码的处理程序。事件泵样式的函数系统在这里很棒,因为它允许您绑定到焦点并执行诸如在输入聚焦时更改背景颜色或边框等操作,而无需自己实现用于捕获输入或显示光标的代码。

当您在输入标签中输入时,输入标签也会引发 input 事件,表明输入已更改,告诉浏览器更改值并更新显示,以便用户期望的功能保持一致。

currency-input 示例中我们添加了 updateValue 函数以与本机函数一起工作并处理事件的输入值,在 updateValue 函数中我们修改了字符串值的表示,需要在某个地方放置它。您可以简单地添加一个数据 属性 来保存值并将输入的值 属性 绑定到数据 属性 允许 currency-input 在内部处理结果的显示但是会将值锁定在私有访问器后面,您将无法修改或检索生成的货币格式值的值。

使用 this.$emit('input', Number(formattedValue))updateValue 函数的行为类似于原生 input 标记,方法是引发可由父上下文捕获并使用的事件。您可以将它存储在一个值中,将其用作函数的基础,甚至可以完全忽略它,尽管这可能没有多大帮助。这允许您跟踪输入的值并根据需要修改它或将其发送到服务器、显示它等。

它还与一些最相关的指令相关联 v-model,它是允许 value 属性 绑定和 input 事件绑定到数据的语法糖属性 在当前上下文中。通过提供 value 属性并发出 input 事件,自定义元素可以像 Vue 应用程序系统中的原生表单元素一样工作。当您想要打包和分发或重用组件时,这是一个非常有吸引力的功能。

去的时候好多了:

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

而不是必须在每个地方添加 valueinput 绑定,因此:

...
<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)'>
...

现在我的怪异漫谈已经结束,我希望这有助于理解 currency-input 示例背后的一些模式和推理。