vue将原生事件绑定到组件--方法详细解释

本文探讨了Vue中组件事件监听的最佳实践,包括使用v-on的.native修饰符的问题与限制,以及如何利用Vue提供的$listeners属性来更有效地处理组件内部的事件监听,确保组件能正确响应外部事件。
  1. 使用 v-on 的 .native 修饰符:
<base-input v-on:focus.native="onFocus"></base-input>

在有的时候这是很有用的,不过在你尝试监听一个类似 的非常特定的元素时,这并不是个好主意。比如上述 组件可能做了如下重构,所以根元素实际上是一个

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

这时,父级的 .native 监听器将静默失败。它不会产生任何报错,但是 onFocus 处理函数不会如你预期地被调用。

**原因:父级元素 的根元素是,元素监听了focus事件,但实际上,事件的触发源是 元素。并且

  • 元素没有focus事件
  • 即使有focus事件,当前template中元素只默认监听了input事件。事件向上传递后,也无法触发根元素事件 **
  1. 使用Vue 提供的一个 $listeners 属性
    Vue 提供了一个 $listeners 属性,它是一个对象,里面包含了作用在这个组件上的所有监听器。例如:
{
  focus: function (event) { /* ... */ }
  input: function (value) { /* ... */ },
}

对于类似 的你希望它也可以配合 v-model 工作的组件来说,为这些监听器创建一个类似下述 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>
  `
})

然后使用方式如下:

<base-input v-on:listener-name="methodName"></base-input>

说明: 上面的代码中, this.listeners其实是获取了&lt;base−input&gt;这个父级组件中定义的所有的监控事件listener−name,再加上input事件,就能使得&lt;base−input&gt;组件像一个普通的&lt;input&gt;元素一样使用了。∗∗特别说明:∗∗如果在&lt;base−input&gt;通过v−on或v−model的方式,监听input事件,那么this.listeners其实是获取了&lt;base-input&gt;这个父级组件中定义的所有的监控事件listener-name,再加上input事件,就能使得&lt;base-input&gt; 组件像一个普通的 &lt;input&gt; 元素一样使用了。 **特别说明:**如果在&lt;base-input&gt; 通过v-on或v-model的方式,监听input事件,那么this.listeners<baseinput>listenernameinput使<baseinput><input>使<baseinput>vonvmodelinputthis.listeners就会取到这个input监听事件,但在Object.assign()时,同名的监听事件,后者会覆盖前者。因此即使在父级组件中定义input监听,也不会出现问题。

另外

<base-input v-on:listener-name="methodName"></base-input>

对组件的子组件建立监控的时候,其实更像是在的实例中定义了一个listener-name为名称的函数,然后通过$emit反射调用。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值