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很相像。

关闭监听

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

猜你喜欢

转载自blog.csdn.net/weixin_45719444/article/details/128376644