<base-input> </base-input> 是一个组件。
用 .native 修饰符 可以把 "focus" 这个原生事件绑定在这个组件上。
但是,如果组件的根元素不能使用 " focus " 事件时,这个绑定会失效。(比如这个组件的父元素是 <label> </label> , 子元素是 <input> </input>, 我们的目的是在 <input> </input> 元素上绑定 "focus" 这个事件, 就不能直接在 <base-input> 组件元素上绑定。因为 v-on: focus,native 绑定的是组件的父元素 )
所以,为了在 <input> </input> 元素上绑定 "focus" 这个事件,
必须在 <input>上用 v-on绑定原生事件:< input v-on: input="$emit('input',$event.target.value)" >
如果想绑定多个原生事件,就需要写很多个 v-on 绑定在这个元素上。
$listeners属性
Vue 提供了一个
$listeners
属性,它是一个对象,里面包含了作用在这个组件上的所有监听器。
这时,可以使用 $listeners
属性,在组件的$listeners
属性里面写好所有将会需要的监听器(原生事件),这些监听器就可以直接绑定在组件的子元素上(不是根元素)。
例子解析:
1. 首先,在computed 计算属性里,创建一个 "inputListeners" 方法。这个方法返回的是这个组件的
监听器。用 object.assign( ) 方法,合并了 this.$listeners (之前创建的监听器) 和 { input: function(event)(vm.$emit('input',event.target.value)) } ( input 就是新创建的事件/监听器)
2. 在 template 模板中,子元素 <input> 用 v-on 直接绑定 "inputListeners" 方法 : <input v-on="inputListeners" >
这样,"inputListeners" 方法里面返回的所有监听器,都被绑在了这个 <input> 这个子元素上了
现在 <base-input> 组件是一个完全透明的包裹器了,也就是说它可以完全像一个普通的 <input> 元素一样使用了:所有跟它相同的特性和监听器的都可以工作