[Vue]组件——使用.native和$listeners将控件的原生事件绑定到组件

1.方法1:.native修饰符

1.1.native修饰符:将原生事件绑定到组件的根元素

<base-input v-on:focus.native="onFocus"></base-input>

1.2缺点:

如以下根元素实际上是一个 <label> 元素时,原生事件不能被绑定到input事件上:

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

2.方法2:$listeners 属性(它是一个对象,里面包含了作用在这个组件上的所有监听器。)

2.1使用 v-on="$listeners" 将所有的事件监听器指向这个组件的某个特定的子元素。

<template>
  <button
    :disabled="mixin_controlDisable"
    :class="$style.button"
    v-on="$listeners"
  >
  </button>
</template>

2.2对于类似 <input> 的你希望它也可以配合 v-model 工作的组件来说,为这些监听器创建一个类似下述 listeners 的计算属性通常是非常有用的:

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> 组件是一个完全透明的包裹器了,也就是说它可以完全像一个普通的 <input> 元素一样使用了:所有跟它相同的特性和监听器的都可以工作。

<base-input v-on:focus="onFocus"></base-input>