Vue 详尽的组件通信

1,815 阅读1分钟

更多个人博客

父子组件通信

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)