超详细的 | vue3组件之间的通信方式(二,兄弟组件)(全局事件总线mitt,$bus、provide和inject方法、pinia)

一、全局事件总线mitt插件$bus

1.全局安装mitt插件

npm install mitt --save

2.使用步骤

在src目录下下创建一个(utils文件夹)新建mitt.ts文件,简单封装一下(怎么创建都行)

import mitt from 'mitt';
const $bus = mitt();
export default $bus;

父组件:BusTest.vue

<template>
  <div class="box">
    <h1>全局事件总线$bus</h1>
    <hr />
    <div class="container">
      <Child1></Child1>
      <Child2></Child2>
    </div>
  </div>
</template>

<script setup lang="ts">
//引入子组件
import Child1 from "./Child1.vue";
import Child2 from "./Child2.vue";
</script>

子组件1:Child1.vue

<template>
  <div class="child1">
    <h3>我是子组件1:曹植</h3>
  </div>
</template>

<script setup lang="ts">
import $bus from "../../bus";
//组合式API函数
import { onMounted } from "vue";
//组件挂载完毕的时候,当前组件绑定一个事件,接受将来兄弟组件传递的数据
onMounted(() => {
  //第一个参数:即为事件类型  第二个参数:即为事件回调
  $bus.on("car", (car) => {
    console.log(car);
  });
});
</script>

子组件2:Child2.vue

<template>
  <div class="child2">
     <h2>我是子组件2:曹丕</h2>
     <button @click="handler">点击我,给兄弟送一台跑车</button>
  </div>
</template>

<script setup lang="ts">
//引入$bus对象
import $bus from '../../bus';
//点击按钮回调
const handler = ()=>{
  $bus.emit('car',{car:"跑车"});
}
</script>

二、provide和inject方法

vue3提供provide(提供)与inject(注入),可以实现隔辈组件传递数据

provideinject方法就是Vue 3实现这种依赖注入的工具。父组件通过provide提供数据,后代组件通过inject获取数据。这种模式特别适用于需要跨组件传递状态或配置的情况。

1.父组件:ProvideInjectTest.vue

<template>
  <div>
    <Child></Child>
  </div>
</template>

<script setup lang="ts">
import Child from "./Child.vue";
import { ref, provide } from "vue";
let car = ref("跑车");
//祖先组件给后代组件提供数据
//两个参数:第一个参数就是提供的数据key
//第二个参数:祖先组件提供数据
provide("TOKEN", car);
</script>

 在这个例子中,我们在setup函数中调用了provide方法,并提供了一个键值对,键是TOKEN,值是我们要传递的数据car的数据。

2.子组件:Child.vue

<template>
  <div class="child">
     <h1>我是子组件1</h1>
     <GrandChild></GrandChild>
  </div>
</template>

<script setup lang="ts">
import GrandChild from './GrandChild.vue';
</script>

3.孙子组件:GrandChild.vue

<template>
  <div class="child1">
    <h1>孙子组件</h1>
    <p>{
   
   {car}}</p>
    <button @click="updateCar">更新数据</button>
  </div>
</template>

<script setup lang="ts">
import {inject} from 'vue';
//注入祖先组件提供数据
//需要参数:即为祖先提供数据的key
let car = inject('TOKEN');
const updateCar = ()=>{
   car.value  = '自行车';
}
</script>

三、pinia的使用(全局组件通信)

vuex:集中式状态管理容器,可以实现任意组件之间的通信
核心概念:state,mutations,actions.getters,modules
pinia:集中式管理状态容器,可以实现任意组件之间的通信
核心概念:state.actions,getters

新建strore仓库,在main.ts中引入并使用

1.在store目录下创建index.ts文件夹 引入pinia

import { createPinia } from 'pinia';
let store = createPinia();
//对外暴露,安装仓库
export default store;

2.在modules文件夹下创建info.ts

//定义info小仓库
import { defineStore } from "pinia";
//第一个仓库:小仓库名字  第二个参数:小仓库配置对象
//defineStore方法执行会返回一个函数,函数作用就是让组件可以获取到仓库数据
let useInfoStore = defineStore("info", {
    //存储数据:state
    state: () => {
        return {
            count: 100,
            arr: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
        }
    },
    actions: {
        //注意:函数没有context上下文对象
        //没有commit、没有mutations去修改数据
        updateNum(a: number, b: number) {
            this.count += a;
        }
    },
    getters: {
        total() {
            let result: any = this.arr.reduce((prev: number, next: number) => {
                return prev + next;
            }, 0);
            return result;
        }
    }
});
//对外暴露方法
export default useInfoStore;

3.页面使用:

<template>
  <div class="son">
    {
   
   { infoStore.count }}--{
   
   { infoStore.total }}
    <button @click="update">点击修改数据</button>
  </div>
</template>
 
<script setup lang="ts">
import userInfoStore from "../../store/modules/info";
// 获取小仓库对象
let infoStore = userInfoStore();
// 修改数据的方法
const update = () => {
  infoStore.count++;
  // 调用自身的方法
  infoStore.updateNum(10, 11); 
};
</script>

四、总结:vue3 (setup)语法糖常用的组件间的通信方式

1.父子组件通信

(1)父到子

  • Props:在父组件中,你可以通过模板中的属性(attributes)或v-bind指令向子组件传递数据。在子组件的setup函数中,这些数据作为props对象的属性被接收。

(2)子到父

  • 自定义事件(Emits):子组件可以使用defineEmits函数定义它可以触发的自定义事件,并通过emit函数触发这些事件。父组件则可以在模板中监听这些事件,并执行相应的回调函数。

2.兄弟组件或跨多级组件通信

(1)Pinia

  • 状态管理:Pinia是Vue 3的官方状态管理库,用于跨组件共享状态。在Pinia中,你可以定义多个store来管理不同领域的数据。每个store都可以包含state(状态)、getters(计算属性)、actions(类似于mutations,用于修改状态)等。
  • 读取状态:在组件的setup函数中,你可以使用useStore函数(根据store的名称或store本身)来获取store的实例,并访问其state或getters。
  • 修改状态:你可以通过直接修改state(如果state是可变的)或使用actions来修改状态。修改后,所有依赖于该状态的组件都会自动更新。
  • 监听状态变化:你可以使用Vue 3的watch函数来监听state或getters的变化,并在变化时执行特定的逻辑。

(2)Provide / Inject

  • 跨层级组件通信provide 和 inject 可以在任何嵌套深度的组件之间传递数据。在祖先组件的setup函数中,你可以使用provide函数提供数据。在后代组件的setup函数中,你可以使用inject函数接收这些数据。这种方式非常适合于插件或高阶组件的开发,其中你需要在多个不直接相关的组件之间共享数据。

(3)Event Bus

  • 全局事件总线:虽然Vue 3和Pinia都提供了更先进的通信方式,但在某些简单场景下,你仍然可以使用全局事件总线(Event Bus)来实现兄弟组件或跨多级组件的通信。然而,由于这种方式可能会导致事件流难以追踪和调试,因此并不推荐在大型项目中使用。

综上所述,Vue 3的setup语法糖结合Pinia为组件之间的通信提供了多种灵活且强大的方式,涵盖了父子组件通信以及兄弟组件或跨多级组件通信的各种场景。

猜你喜欢

转载自blog.csdn.net/weixin_48642777/article/details/141683571