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.这个例子写的很清楚,但是不懂什么意思,求大佬解释解释。
首先,
$listeners
是什么?假设有父组件
Parent
和子组件Child
那么你在使用
Child
时,传入的所有v-on事件都可以在$listeners
对象中找到。所以,官方示例中的
computed -> inputListeners
就是把用户使用base-input
组件时传入的v-on
方法收集起来了。然后通过
v-on="inputListeners"
的形式,转发给了input框。(
v-on="{a: f()}"
等价于v-on:a="f()"
)所以官网才会说base-input是一个透明包裹器,因为它确实只是转发了父组件传入的参数给input元素。