官方文档地址
$listeners是vue提供的一个对象,里面包含了所有作用在这个组件上的监听器。
比如你要自定义一个input组件,需要监听input获取焦点的事件
你可以这样做
自定义组件代码
<template>
<div>
<input type="text" v-on:focus="handleFocus" v-on:input="handleInput" />
</div>
</template>
<script>
export default {
name: "ListenersDemo",
props:{
value: String
},
methods:{
handleFocus(event){
this.$emit("focused",event)
},
handleInput(event){
this.$emit("input",event)
}
}
}
</script>
父组件代码
<listeners-demo class="my-btn" v-on:focused="handleFocus" v-on:input="input" ></listeners-demo>
这样就可以实现预期的功能,但是你也可以使用更优雅的做法
修改之后
自定义组件代码
<template>
<div>
<!-- 接管所有原生监听事件-->
<!-- <input type="text" v-on="$listeners" />-->
<!-- 自定义监听器 接管所有原生监听事件 可添加自定义监听事件并可以配合v-model使用-->
<input type="text" v-on="inputListeners" v-bind:value="value" />
</div>
</template>
<script>
export default {
name: "ListenersDemo",
props:{
value: String
},
computed:{
inputListeners(){
var vm = this
// `Object.assign` 将所有的对象合并为一个新对象
return Object.assign({},
// 我们从父级添加所有的监听器
this.$listeners,
// 然后我们添加自定义监听器,
// 或覆写一些监听器的行为
{
// 这里确保组件配合 `v-model` 的工作
input: function (event) {
// 重写了input监听器,你也可以理解为自定义了一个名为input的监听器
vm.$emit('input', event.target.value)
}
}
)
}
},
}
</script>
父组件完整代码
<template>
<div>
<listeners-demo v-on:focus="handleFocus" v-on:input="handleInput" v-model="value" ></listeners-demo>
</div>
</template>
<script>
import ListenersDemo from "@/components/ListenersDemo";
export default {
name: "home",
components: {
ListenersDemo
},
data: () => ({
value: '111111'
}),
methods:{
handleInput(value){
// eslint-disable-next-line no-console
console.log(value)
},
handleFocus(event){
// eslint-disable-next-line no-console
console.log(event)
}
}
}
</script>
使用v-on="$listeners"
将所有的事件监听器指向这个组件的某个特定的子元素
也可以使用一个计算属性重写$listeners
,上面代码中使用inputListeners
重写了$listeners
这样就不用为每一个监听器写一个监听函数
网友评论