VUE 组件间通信方式

2,257 阅读2分钟

前言

组件间的作用域是相互独立的,这就意味着不同组件之间的数据无法相互引用,接下来,我们就悉数给大家展示所有 Vue 组件之间的通信方式。

通信方案

  1. Props传递数据 (常用)
  2. $emit (组件封装用的较多)
  3. attrs & listeners
  4. Provide & Inject
  5. Ref使用
  6. EventBus
  7. Vuex通信

Props传递数据

简单来说,我们可以通过 Prop 向子组件传递数据。用一个形象的比喻来说,父子组件之间的数据传递相当于自上而下的下水管子,只能从上往下流,不能逆流。

父组件代码演示

子组件代码演示

$emit使用

父组件向子组件传递数据是通过prop传递的,子组件传递数据给父组件是通过$emit触发事件来做到的。

父组件代码演示

子组件代码演示

$attrs 和 $listeners

第一种方式处理父子组件之间的数据传输有一个问题:如果多层嵌套,父组件A下面有子组件B,组件B下面有组件C,这时如果组件A想传递数据给组件C怎么办呢?

如果采用第一种方法,我们必须让组件A通过prop传递消息给组件B,组件B在通过prop传递消息给组件C;要是组件A和组件C之间有更多的组件,那采用这种方式就很复杂了。从Vue 2.4开始,提供了$attrs和$listeners来解决这个问题,能够让组件A之间传递消息给组件C。

$attrs

批量向下传入属性

<Son2 name="小文强" age="10"></Son2>

<!-- 可以在son2组件中使用$attrs属性,可以将属性继续向下传递 -->
<div>
  儿子2: {{$attrs.name}}
  <Grandson2 v-bind="$attrs"></Grandson2>
</div>

<template>
 <div>孙子:{{$attrs}}</div>
</template>

$listeners

<Son2 name="小文强" age="10" @click="()=>{this.mny = 500}"></Son2>
<!-- 可以在son2组件中使用listeners属性,可以将方法继续向下传递 -->
<Grandson2 v-bind="$attrs" v-on="$listeners"></Grandson2>

<button @click="$listeners.click()">更改</button>

Provide 和 Inject

父组件中通过provider来提供变量,然后在子组件中通过inject来注入变量。不论子组件有多深,只要调用了inject那么就可以注入provider中的数据。而不是局限于只能从当前父组件的prop属性来获取数据,只要在父组件的生命周期内,子组件都可以调用。

Provide

provide() {
  return { parentMsg: "父亲" };
},

Inject

inject: ["parentMsg"] // 会将数据挂载在当前实例上

Ref使用

Ref可以直接获取组件的实例

<Grandson2 v-bind="$attrs" v-on="$listeners" ref="grand2"></Grandson2>
mounted() { // 获取组件定义的属性
  console.log(this.$refs.grand2.name);
}

EventBus

思路就是声明一个全局Vue实例变量 EventBus , 把所有的通信数据,事件监听都存储到这个变量上。这样就达到在组件间数据共享了,有点类似于 Vuex。但这种方式只适用于极小的项目,复杂项目还是推荐 Vuex。

Vue.prototype.$bus = new Vue();

Son2组件和Grandson1相互通信

 mounted() {
  this.$bus.$on("my", data => {
   console.log(data);
  });
 },
mounted() {
  this.$nextTick(() => {
   this.$bus.$emit("my", "我是Grandson1");
  });
 },

Vuex处理组件之间的数据交互

如果业务逻辑复杂,很多组件之间需要同时处理一些公共的数据,这个时候才有上面这一些方法可能不利于项目的维护,vuex的做法就是将这一些公共的数据抽离出来,然后其他组件就可以对这个公共数据进行读写操作,这样达到了解耦的目的。