Vue组件间通信的10+种方法part2($listeners详细介绍)
接着上一篇《Vue组件间通信的10+种方法part1($attrs详细介绍)》,这篇文章是介绍$listeners的, $listeners可以说是$emit的竞品。
1 官方文档的介绍
包含了父作用域中的 (不含 .native
修饰器的) v-on
事件监听器。它可以通过 v-on="$listeners"
传入内部组件——在创建更高层次的组件时非常有用。
2 为什么要使用$listeners?而不是$emit?
考虑以下情况
(1)子组件向父组件$emit多种方法
(2)孙组件向爷组件传递消息
这些情况和prop,$attrs面临的情景时对应的。第一种情况,需要在父组件v-on绑定多个方法;第二种情况分级地进行$emit过于繁琐。这些情景下,使用$listeners会更加方便、代码更美观。
3 怎么用$listeners?
同样采用爷组件、父组件、子组件的例子
Grand.vue, 爷爷绑定了test1和test2事件
<template>
<div>
<parent v-on:test1="test1" v-on:test2="test2" v-on:test3="test3"></parent>
</div>
</template>
<script>
import Parent from '@/pages/listeners/Parent.vue'
export default {
data () {
return {
name: 'Grand Wall'
}
},
components: {
Parent
},
methods: {
test1 () {
console.log('from parent first')
},
test2 () {
console.log('from parent second')
},
test3 () {
console.log('from child')
}
}
}
Parent.vue, 爸爸v-on绑定了$listeners,并且$emit test1和test2
<template>
<div>
<child v-on="$listeners"></child>
<p>{{name}}</p>
</div>
</template>
<script>
import Child from '@/pages/listeners/Child.vue'
export default {
inheritAttrs: true,
data () {
return {
name: 'Parent Heart'
}
},
components: {
Child
},
mounted () {
this.$emit('test1')
this.$emit('test2')
}
}
</script>
Child.vue 孙子$emit test3
<template>
<div>
<p>{{name}}</p>
</div>
</template>
<script>
export default {
inheritAttrs: true,
data () {
return {
name: 'Child Hood'
}
},
mounted () {
this.$emit('test3')
}
}
</script>
运行代码,结果
总之,就是父组件绑定了v-on="$listeners"以后,孙子组件$emit的方法, 都会发到爷爷组件那里去。当然父组件本身的方法也会发到爷爷组件那里去,这个与$listeners无关,是$emit和$on的机制
4 疑问:如果在父组件上同时使用$listeners和v-on:test3会怎么样?
<template>
<div>
<child v-on="$listeners" @test3="handSelf"></child>
<p>{{name}}</p>
</div>
</template>
<script>
import Child from '@/pages/listeners/Child.vue'
export default {
inheritAttrs: true,
data () {
return {
name: 'Parent Heart'
}
},
components: {
Child
},
mounted () {
this.$emit('test1')
this.$emit('test2')
},
methods: {
handSelf () {
console.log('get msg from son')
}
}
}
</script>
结果:都生效了