vue实现组件通信的方式有:
- 父子通信
父组件向子组件传递通过props定义各个属性来传递,子组件向父组件传递通过$emit触发事件
ref也可以访问组件实例 - 跨级通信
vuex
bus
provide / inject
$attrs / $listeners - 解释 $attrs / $listeners
$attrs 将父组件中不被认为是props特性绑定的属性(即在父组件中或者中间组件中没有在props中定义的属性)传到孙组件中;
$listeners 将父组件标签上的自定义事件向下传递,其子组件可以直接通过$emit的方式调用;
父组件传值给子组件, 子组件可以全部不接受,然后通过v-bind=“$attrs”,传给孙组件, 然后孙组件直接使用props接受父组件传过来的所有属性普通的emit只能从子组件传到父组件, 通过$listeners可以实现从孙子组件把事件传到父组件中去, 不需要通过$emit逐层传递;
<!-- A.vue -->
<template><div><p>这是父组件</p><p>参数: name="fu" age="60" sex="nan-fu" address="shanghai-fu"</p><hr><B name="fu" age="60" sex="nan-fu" address="shanghai-fu" v-bind="$attrs" @setVal="getFuDetail"></B></div>
</template><script>
import B from './B'
export default {components: {B,},methods: {getFuDetail(val) {console.log('这是父组件的方法', val)}}
}
</script><style></style><!-- B.vue -->
<template><div><p>这是子组件</p><p>参数:name="zi" address="beijing-zi"</p><p>props: name</p><p>attrs: {{ $attrs }}</p><p>因为在B组件中props中包含name, 所以在attrs中,只有age,sex,address</p><hr><C name="zi" address="beijing-zi" v-on="$listeners"></C></div>
</template><script>
import C from './C.vue'
export default {components: {C,},props: {name: { type: String, default: ''},},methods: {getZiDetail() {console.log('这是子组件的方法')}}}
</script><style></style><!-- C.vue -->
<template><div><p>这是孙子组件</p><p>props: age</p><p>attrs: {{ $attrs }}</p><p>因为在C组件中props定义了age, 所以attrs中包含:父组件的name, sex, address,子组件的name, address,而子组件的name, address覆盖了父组件的name, address</p><hr></div>
</template><script>
export default {props: {age: { type: String, default: ''},},created() {this.getSunDetail()},methods: {getSunDetail() {console.log('这是孙组件的方法')this.$emit('setVal','通过$listeners触发父组件的事件')}}
}
</script><style></style>
通过$listeners在c组件触发了A组件的方法