官方文檔地址
$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
這樣就不用爲每一個監聽器寫一個監聽函數