怎么理解vue中$listeners属性?官网的例子不是很明白,求指教?

1.官网一开始举例在一个组件的根元素上监听一个原生事件可以用v-on的.native修饰符,例如
<base-input v-on:focus.native="onFocus"></base-input>
2.但是<base-input>内部如果做了重构,根元素实际上是个<label>元素,

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

这时父级的.native监听器将失效,所以vue提供了$listeners属性
3.接下来的举例不是很明白,例子如下:

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> 元素一样使用了:所有跟它相同的特性和监听器的都可以工作。
4.这个例子写的很清楚,但是不懂什么意思,求大佬解释解释。

阅读 4.7k
1 个回答

首先,$listeners是什么?

假设有父组件Parent和子组件Child

// Parent
<template>
  ...
  <child v-on:event-one="methodOne" v-on:event-two="methodTwo" />
  ...
</template>

那么你在使用Child时,传入的所有v-on事件都可以在$listeners对象中找到。

// Child
created () {
  console.log(this.$listeners) // { 'event-one': f(), 'event-two': f() }
}

所以,官方示例中的computed -> inputListeners就是把用户使用base-input组件时传入的v-on方法收集起来了。
然后通过v-on="inputListeners"的形式,转发给了input框。
v-on="{a: f()}"等价于v-on:a="f()"

所以官网才会说base-input是一个透明包裹器,因为它确实只是转发了父组件传入的参数给input元素。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题