vue之非父子组件通信实现方式

在开发中,我们构建了组件树之后,除了父子组件之间的通信之外,还会有非父子组件之间的通信。这里主要讲两种方式:

 

 

  1. Provide/Inject
  2. Mitt全局事件总线

1、Provide和Inject

应用场景

比如有一些深度嵌套的组件,子组件想要获取父组件的部分内容在这种情况下,如果我们仍然将props沿着组件链逐级传递下去,就会非常的麻烦。

对于这种情况下,我们可以使用 Provide和Inject,它可以实现非父子组件之间共享数据

特点

  • 无论层级结构有多深,父组件都可以作为其所有子组件(包括子孙)的依赖提供者
  • 父组件有一个provide选项来提供数据。
  • 子组件有一 inject 选项来使用数据。
实际上,你可以将依赖注入看作是“ long range props”(作用域绵长的props)
父组件不需要知道哪些子组件使用它 provide 的 property;子组件不需要知道 inject 的 property 来自哪里。一般用的不多,提供一些主题、样式之类的。

基本使用

我们编写如下一个组件结构:

 

 

注:不能在定义provide属性的当前组件使用provide提供的数据,兄弟组件也不行。

踩坑

上图中的this指向谁?能不能访问到data里names的长度?为什么?

tips:在这script标签包裹的一段export代码属于一个模块作用域,此时this为undefined。

解决方法是改写provide为函数形式并返回一个对象(像组件里data一样)。

处理响应式数据 

另外如果我们修改了this.names的内容,那么使用length的子组件会不会也发生相应的改变呢?

答案是否定的,因为length不是响应式数据(类似值拷贝)。 所以我们可以使用一些响应式的一些API来完成这些功能,比如说computed函数(vue3语法)。

注:因为 computed返回的是一个ref对象 ,需要手动通过.value形式获取其中真正的值

全局事件总线

Vue3从实例中移除了 $on、$off 和 $once 方法,所以如果希望继续使用全局事件总线,要通过第三方的库。Vue3官方有推荐一些库,例如 mitt 或 tiny-emitter 这里主要介绍一下 mitt库 的使用;

安装

npm install mitt

基本使用

封装一个工具类 eventbus.js:
import mitt from 'mitt';

const emitter = mitt();
// 可以创建多个
// export const emitter1 = mitt();
// export const emitter2 = mitt();
// export const emitter3 = mitt();

export default emitter;
在Home.vue中监听事件

 

在App.vue中触发事件

个人感觉这个api和socket很相像。

关闭监听

在某些情况下我们可能希望 取消掉之前注册的函数监听。

 

Vue 2 中,父子组件之间的通信可以通过事件总线、Vuex 和 provide/inject 来实现。 1. 事件总线 (Event Bus): 在 Vue 实例上创建一个中央事件总线,其他组件可以订阅和触发事件。这种方式适用于简单的组件通信场景。 - 创建事件总线: ```javascript // main.js Vue.prototype.$bus = new Vue(); ``` - 在发送组件中触发事件: ```javascript this.$bus.$emit('event-name', data); ``` - 在接收组件中订阅事件: ```javascript mounted() { this.$bus.$on('event-name', (data) => { // 处理接收到的数据 }); }, ``` 2. Vuex: Vuex 是 Vue.js 官方提供的状态管理库,用于在组件之间共享状态。父子组件通过 Vuex 存储和获取数据。 - 定义和导出 store: ```javascript // store.js import Vue from 'vue'; import Vuex from 'vuex'; Vue.use(Vuex); export default new Vuex.Store({ state: { data: null, }, mutations: { setData(state, payload) { state.data = payload; }, }, actions: { updateData({ commit }, payload) { commit('setData', payload); }, }, }); ``` - 在发送组件中使用 dispatch 触发 action: ```javascript this.$store.dispatch('updateData', data); ``` - 在接收组件中使用 mapState 辅助函数获取数据: ```javascript computed: { ...mapState(['data']), }, ``` 3. provide/inject: 使用 provide 和 inject 实现父子组件之间的数据传递。这种方式适用于跨层级的组件通信。 - 在父组件中使用 provide 提供数据: ```javascript provide() { return { data: this.data, }; }, ``` - 在子组件中使用 inject 注入数据: ```javascript inject: ['data'], ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值