Vue 组件间通信方式

Vue 组件间通信主要指以下 3 类通信:父子组件通信、隔代组件通信、兄弟组件通信。

通信方式及用法:

1、props / $emit 适用父子组件通信

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

使用方法:

父组件 A.vue

<template>
  <div style="background-color: skyblue;width: 300px">
    <h3>这是A</h3>
    // 向B传入了一个属性和一个方法
    <b-child :nameB="nameB" @changeName="changeName"></b-child>
  </div>
</template>

<script>
import BChild from "./B.vue";

export default {
  name: "A",
  components: {BChild},
  data() {
    return {
      nameB: '这是子组件B'
    }
  },
  methods: {
    changeName(nameB) {
      this.nameB = nameB;
    }
  }
}
</script>

子组件B.vue

<template>
  <div style="background-color: pink;">
    <h3>{{ nameB}}</h3>
    <button @click="changeName">更改名字</button>
  </div>
</template>

<script>
export default {
  name: "B",
  props: ['nameB'],// 接收A传递过来的属性
  methods: {
    changeName() {
      this.$emit('changeName', '我是A的子组件B');// 调用A传过来的方法
    }
  }
}
</script>

2、ref / children 适用父子组件通信

ref:如果在普通的 DOM 元素上使用,引用指向的就是 DOM 元素;如果用在子组件上,引用就指向组件实例。

children:访问父 / 子实例。

使用方法:

父组件 A.vue

<template>
  <div style="background-color: skyblue;width: 300px">
    <h3>这是A</h3>
    <b-child ref="child"></b-child>
  </div>
</template>

<script>
import BChild from "./B.vue";

export default {
  name: "A",
  components: {BChild},
  mounted() {
    //通过$ref调用B的方法
    this.$refs.child.getName();
    //通过$children调用B的方法
    //注意:$children返回的是一个数组,当有多个子组件的时候注意区分
    this.$children[0].getName();
  }
}
</script>

子组件 B.vue

<template>
  <div style="background-color: pink;">
    <h3>{{ name }}</h3>
  </div>
</template>

<script>
export default {
  name: "B",
  data() {
    return {
      name: '我是A的子组件B'
    }
  },
  methods: {
    getName() {
      console.log(this.name);
    }
  }
}
</script>

3、EventBus 适用于父子、隔代、兄弟组件通信

这种方法通过一个空的 Vue 实例作为中央事件总线(事件中心),用它来触发事件和监听事件,从而实现任何组件间的通信,包括父子、隔代、兄弟组件。

使用方法:

先在main.js引入

import Vue from 'vue'
Vue.prototype.$EventBus = new Vue();

隔代组件 A.vue

<template>
  <div style="background-color: skyblue;width: 300px">
    <h3>这是A</h3>
    <b-child ref="child"></b-child>
  </div>
</template>

<script>
import BChild from "./B.vue";

export default {
  name: "A",
  components: {BChild},
  mounted() {
    this.$EventBus.$on('getMessage', (message) => {
      console.log('这是C的message信息:', message);
    })
  },
  beforeDestroy() {
    console.log('----销毁监听事件,负责会导致了内存泄露----')
    this.$EventBus.$off('getMessage');
  }
}
</script>

隔代组件 C.vue

<template>
  <div style="background-color: yellow;">
    <h3>这是C</h3>
    <button @click="sendMessage">向A发送信息</button>
  </div>
</template>

<script>
export default {
  name: "C",
  methods: {
    sendMessage() {
      this.$EventBus.$emit('getMessage', 'yes');
    }
  }
}
</script>

4、attr / listeners 适用于隔代组件通信

使用方法:

父组件 A.vue

<template>
  <div style="background-color: skyblue;width: 300px">
    <h3>这是A</h3>
    <b-child nameB="这是B" nameC="这是C" @handleClick="handleClick"></b-child>
  </div>
</template>

<script>
import BChild from "./B.vue";

export default {
  name: "A",
  components: {BChild},
  methods: {
    handleClick() {
      console.log('事件触发了');
    }
  },
}
</script>

A的子组件 B.vue

<template>
  <div style="background-color: pink;">
    <h3>{{ nameB }}</h3>
    <!-- 通过 v-bind 绑定$attrs属性,C组件可以直接获取到A组件中传递下来的props(除了B组件中props声明的) -->
    <!-- 通过 v-on 绑定了$listeners 属性 -->
    <c-child v-bind="$attrs" v-on="$listeners"></c-child>
  </div>
</template>

<script>
import CChild from "./C.vue";

export default {
  name: "B",
  components: {CChild},
  props: ["nameB"]
}
</script>

B的子组件 C.vue

<template>
  <div style="background-color: yellow;">
    <h3>{{ nameC }}</h3>
    <button @click="handleClick">点击</button>
  </div>
</template>

<script>
export default {
  name: "C",
  props: ["nameC"],
  methods: {
    handleClick() {
      this.$emit('handleClick');
    }
  }
}
</script>

5、provide / inject 适用于隔代组件通信

祖先组件中通过 provider 来提供变量,然后在子孙组件中通过 inject 来注入变量。provide / inject API 主要解决了跨级组件间的通信问题,不过它的使用场景,主要是子组件获取上级组件的状态,跨级组件间建立了一种主动提供与依赖注入的关系。

使用方法:

父组件 A.vue

<template>
  <div style="background-color: skyblue;width: 300px">
    <h3>这是A</h3>
    <b-child nameB="这是B"></b-child>
  </div>
</template>

<script>
import BChild from "./B.vue";

export default {
  name: "A",
  components: {BChild},
  provide() {
    return {
      btnClick: this.handleClick// 传递
    }
  },
  methods: {
    handleClick() {
      console.log('事件触发了');
    }
  },
}
</script>

子组件 B.vue

<template>
  <div style="background-color: pink;">
    <h3>{{ nameB }}</h3>
    <button @click="handleClick">点击</button>
  </div>
</template>

<script>
export default {
  name: "C",
  props: ["nameB"],
  inject: ["btnClick"],// 接收
  methods: {
    handleClick() {
      this.btnClick();
    }
  }
}
</script>

6、Vuex 适用于 父子、隔代、兄弟组件通信

Vuex在这里就不做讲解了,详情查看 vuex文档

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值