父子组件通信
1. props
最常规的父子组件传值方法,在此不多赘述
值得一提的是,子组件中可以用 $attrs 获取父组件传来的所有属性(除了 class、style),从而不用一个个声明 prop。
如果不用 prop 声明接收,Vue 会默认将这些属性挂载到 子组件的 dom 根元素上。如果不希望这样,可以设置 inheritAttrs 去除这一默认行为。
export default {
inheritAttrs: false
}
如果需要传给更深一层的子组件,只需通过 v-bind="$attrs" 传入
2. 分发事件
除了 $emit 可以向父组件分发事件之外
还有一个与 $attrs 类似的一个 api :$listener,可以拿到父组件上的所有事件监听器。同样的,v-on="$listeners" 可以将之传给更深一层的子组件
通过 $listeners.xxx 可以直接触发父组件的 xxx 监听器
3. 插槽
插槽最常见的用法是:在子组件中使用 slot 插槽,在父组件中对其进行填充,可以是具名插槽也可以是匿名插槽。
除了这种用法以外,父组件还可以拿到子组件在插槽上传递的数据,也就是作用域插槽:
子组件中通过 v-bind 绑定数据
<template>
<div class="child">
<slot v-bind:data="data"></slot>
</div>
</template>
父组件中可以通过 v-slot 接收
<child v-slot:default="slotData">
{{ slotData.data }}
</child>
4. 父组件的共享 — 注入
父组件可以将一些共享的数据注入,后代通过 inject 选项接收后直接可以使用,这些数据将会是共享的。
// 父组件中
provide(){
return {
parentData: this.data
}
}
// 子组件中
inject: ['parentData']
// 通过 this.parentData 即可访问
甚至,你还可以将父组件整个共享:
provide(){
return {
parent: this
}
}
5. 父链子链
通过 this.$parent 可以访问到父组件的数据,this.$parent.$parent 可以访问到爷组件。
与此类似,还有 this.$children
但是过度使用可能会造成代码混乱,尤其是组件嵌套很深时。
非父子组件通信
eventBus
// 父组件
data(){
return {
bus: new Vue()
}
}
provide(){
return {
eventBus: this.bus
}
}
这里借用到上面的注入方法,不过这次注入的是一个 Vue 实例,原因是:这里注入的内容应该是一个事件中心,刚好 Vue 实例提供了 $on $emit 方法,我们可以直接借用
至于为什么要放在 data 中,是因为这样父组件也可以拿到这个 eventBus,也可以进行事件的监听和分发。
在其他组件中接收这个事件中心:
inject: ['eventBus']
当需要监听事件时,只需要通过 $on 添加事件监听器即可:
this.eventBus.$on('change', (data) => {
// ...
})
当分发一个事件后,所有监听了这个事件的组件都会触发回调,拿到传递的数据:
this.$eventBus.$emit('change', someData)