首页 > 其他分享 >Vue3组件通信详解

Vue3组件通信详解

时间:2024-09-04 09:25:42浏览次数:7  
标签:订阅 mitt eventName 详解 事件 Vue3 组件 emit

Vue 3 中的组件通讯是 Vue 应用开发中非常重要的一环,它允许组件之间传递数据和方法,从而实现数据的共享和功能的调用。下面将分别介绍父子组件、孙子组件(祖孙组件)、兄弟组件之间的通讯方式,并给出示例代码和总结表格。

一、父子组件通讯

1. 父传子(props)

父组件通过 props 向子组件传递数据。

父组件示例代码

<template>  
  <ChildComponent :message="parentMessage" />  
</template>  
  
<script setup>  
import ChildComponent from './ChildComponent.vue';  
import { ref } from 'vue';  
  
const parentMessage = ref('Hello from Parent');  
</script>

子组件示例代码

<template>  
  <div>{{ message }}</div>  
</template>  
  
<script setup>  
import { defineProps } from 'vue';  
  
const props = defineProps({  
  message: String  
});  
</script>

2. 子传父($emit)

子组件通过 $emit 触发事件,向父组件传递数据或信号。

子组件示例代码

<template>  
  <button @click="sendMessage">Send Message to Parent</button>  
</template>  
  
<script setup>  
//this.$emit->”定义emit“,传数据
const emit = defineEmits(['update:message']);  
  
function sendMessage() {  
  emit('update:message', 'Hello from Child');  
}  
</script>

父组件示例代码(监听子组件触发的事件):

<template>  
  <ChildComponent @update:message="handleMessage" />  
</template>  
  
<script setup>  
import ChildComponent from './ChildComponent.vue';  
  
function handleMessage(message) {  
  console.log(message); // 输出: Hello from Child  
}  
</script>

二、祖孙组件通讯(provide/inject)

祖先组件通过 provide 选项提供数据或方法,后代组件通过 inject 选项接收数据或方法。

祖先组件示例代码

<template>  
  <ChildComponent />  
</template>  
  
<script setup>  
import { provide, ref } from 'vue';  
  
const grandParentData = ref('Data from GrandParent');  
  
provide('grandParentData', grandParentData);  
</script>

三、兄弟组件通讯

兄弟组件之间的通讯通常不直接进行,而是通过共同的父组件或全局状态管理(如 Vuex、Pinia)来实现。

示例:通过事件总线(不推荐,Vue 3 中可用第三方库如 mitt 替代)

事件总线(mitt.js)

// eventBus.js  
import mitt from 'mitt';  
const emitter = mitt();  
export default emitter;

组件A(发送方)

<template>  
  <button @click="sendMessage">Send Message to Brother</button>  
</template>  
  
<script setup>  
import emitter from './eventBus.js';  
  
function sendMessage() {  
  emitter.emit('message', 'Hello from Component A');  
}  
</script>

组件B(接收方)

<template>  
  <p>{{ message }}</p>  
</template>  
  
<script setup>  
import { ref } from 'vue';  
import emitter from './eventBus.js';  
  
const message = ref('');  
 //emitter.on接收,‘message’通信主体标识
emitter.on('message', (newMessage) => {  
  message.value = newMessage;  
});  
</script>

四、总结

通讯类型通讯方式发送方接收方示例说明
父子组件props父组件子组件父组件通过 props 传递数据给子组件
父子组件$emit子组件父组件子组件通过 $emit 触发事件,父组件监听并处理
祖孙组件provide/inject祖先组件后代组件祖先组件通过 provide 提供数据,后代组件通过 inject 接收
兄弟组件通过父组件兄弟组件A兄弟组件B兄弟组件A通过事件通知父组件,父组件再传递给兄弟组件B
兄弟组件全局状态管理(Vuex/Pinia)兄弟组件A兄弟组件B使用 Vuex 或 Pinia 管理全局状态,兄弟组件共享状态
兄弟组件第三方库(如 mitt)兄弟组件A兄弟组件B通过第三方库实现事件总线,兄弟组件间通过事件总线通讯

 五、事件总线底层原理

设计模式—观察者模式与发布订阅-CSDN博客

Javascript常见设计模式-CSDN博客

发布——订阅者模式

发布-订阅模式是一种消息传递模式,允许发送者(发布者)发送消息而不直接关心谁将接收这些消息,同时接收者(订阅者)可以监听并接收这些消息,而不需要了解消息是从哪里发送的。mitt 作为一个轻量级的事件总线库,正是基于这种模式设计的。

在 mitt 中,你可以:

  • 使用 .on(eventName, handler) 方法来订阅一个事件,其中 eventName 是事件的名称(一个字符串),而 handler 是当事件发生时被调用的处理函数。
  • 使用 .emit(eventName, ...args) 方法来发布一个事件,其中 eventName 是事件的名称,而 ...args 是传递给事件处理函数的参数列表。
  • (可选地)使用 .off(eventName, handler) 方法来取消订阅之前订阅的事件。如果不提供 handler,则取消该事件的所有订阅者。

这些操作完全符合发布-订阅模式的典型特征:

  • 发布者(在 mitt 的上下文中是调用 .emit() 方法的代码)发布一个事件,不需要知道有哪些订阅者会接收这个事件。
  • 订阅者(在 mitt 的上下文中是通过 .on() 方法注册的处理函数)监听并响应特定的事件,不需要知道事件是由谁发布的。
  • 事件总线(在 mitt 的上下文中是 mitt 实例本身)负责事件的分发,确保事件能够到达所有相关的订阅者。

因此,可以说 mitt 确实是通过发布-订阅模式来实现其功能的。

// 创建一个简单的发布订阅者管理类  
class EventEmitter {  
    constructor() {  
        this.events = {}; // 用于存储事件的字典,键为事件名,值为订阅者数组  
    }  
  
    // 订阅事件  
    on(eventName, callback) {  
        if (!this.events[eventName]) {  
            this.events[eventName] = []; // 如果该事件尚未被订阅,则初始化一个空数组  
        }  
        this.events[eventName].push(callback); // 将回调函数添加到订阅者数组中  
        return this; // 支持链式调用  
    }  
  
    // 取消订阅事件  
    off(eventName, callback) {  
        if (this.events[eventName]) {  
            // 移除指定的回调函数  
            this.events[eventName] = this.events[eventName].filter(cb => cb !== callback);  
            // 如果订阅者数组为空,则删除该事件  
            if (this.events[eventName].length === 0) {  
                delete this.events[eventName];  
            }  
        }  
        return this; // 支持链式调用  
    }  
  
    // 发布事件  
    emit(eventName, ...args) {  
        if (this.events[eventName]) {  
            // 遍历订阅者数组,并执行每个回调函数  
            this.events[eventName].forEach(callback => {  
                callback.apply(this, args);  
            });  
        }  
        return this; // 支持链式调用  
    }  
  
    // 可选:监听一次后自动取消订阅  
    once(eventName, callback) {  
        const onceCallback = (...args) => {  
            callback.apply(this, args);  
            this.off(eventName, onceCallback);  
        };  
        this.on(eventName, onceCallback);  
        return this; // 支持链式调用  
    }  
}  
  
// 使用示例  
const eventBus = new EventEmitter();  
  
// 订阅者1  
function subscriber1(price) {  
    console.log('订阅者1收到消息:当前价格已降至' + price + '元');  
}  
  
// 订阅者2  
function subscriber2(price) {  
    console.log('订阅者2也收到消息:价格更新为' + price + '元');  
}  
  
// 订阅事件  
eventBus.on('priceUpdate', subscriber1);  
eventBus.on('priceUpdate', subscriber2);  
  
// 使用once方法监听一次  
eventBus.once('specialOffer', (offer) => {  
    console.log('只接收一次的特别优惠:' + offer);  
});  
  
// 发布事件  
eventBus.emit('priceUpdate', 99); // 订阅者1和订阅者2都会收到消息  
eventBus.emit('specialOffer', '买一赠一'); // 只有一个订阅者会收到这个特别优惠的消息  
  
// 取消订阅  
eventBus.off('priceUpdate', subscriber1);  
eventBus.emit('priceUpdate', 88); // 只有订阅者2会收到消息

标签:订阅,mitt,eventName,详解,事件,Vue3,组件,emit
From: https://blog.csdn.net/m0_55049655/article/details/141872778

相关文章

  • jstack命令详解【转】
    jstack命令详解  简介jstack命令用于打印指定Java进程、核心文件或远程调试服务器的Java线程的Java堆栈跟踪信息[1]。jstack命令可以生成JVM当前时刻的线程快照。线程快照是当前JVM内每一条线程正在执行的方法堆栈的集合,生成线程快照的主要目的是定位线程出现长时间停顿......
  • clickhouse组件介绍
    写在前面今天学习clickhouse部分的知识。ClickHouseOLTP(联机事务处理系统)例如MySQL等关系型数据库,适用于小数据量时的快速查询和分析。OLTP主要针对增删改操作,数据经常发生变化。OLAP(联机分析处理系统)适用于数据长期不变且有大量历史数据的场景,主要进行分析操作,增......
  • Linux服务器之TOP命令详解
    在做性能调优的过程中,我们经常需要用到top命令来查看服务器实时的资源占用情况,通过top命令,我们可以查看到服务器的各项性能指标以及各个进行的资源使用情况。命令格式:top[参数]命令参数:-b批处理-c显示完整的治命令-I忽略失效过程-s保密模式-S累积模式-i<......
  • Nginx中的limit_req模块和limit_conn模块详解
    引言在高流量场景下,良好的限流和连接控制策略至关重要,以防止服务器过载,确保服务稳定性和高可用性。Nginx提供了limit_req和limit_conn模块,用以实现请求频率和并发连接数的限制。本文将详细介绍这两个模块的生效阶段和生效范围,并提供实际配置示例,解释相关指令的作用。limit_re......
  • django Form组件校验流程
    django中Form组件字段校验顺序:先字段内部校验,然后钩子方法校验:fromdjango.shortcutsimportrender,redirectfromdjango.core.validatorsimportRegexValidatorfromdjangoimportformsfromapp01.utilss.mdyimportmdfromapp01.modelsimportAdministrator,Custom......
  • 大二必做项目贪吃蛇超详解之下篇游戏核心逻辑实现
    贪吃蛇系列文章上篇win32库介绍中篇设计与分析下篇游戏主逻辑可以在Gitee上获取贪吃蛇代码。文章目录贪吃蛇系列文章5.核心逻辑实现分析5.3GameRun5.3.1PrintScore5.3.2CheckVK5.3.3BuyNewNode5.3.4NextIsFood5.3.4EatFood5.3.5NotFood5.3.6C......
  • 搜索组件优化 - Command ⌘K
    前言:DevNow项目中我们使用了DocSearch来实现搜索功能,但是由于有以下的限制:您的网站必须是技术文档或技术博客。您必须是网站的所有者,或者至少具有更新其内容的权限您的网站必须公开可用您的网站必须已准备好生产环境。由于这些条件的限制,DocSearch只适合用在开源的技......
  • Datawhale X 李宏毅苹果书 AI夏令营-深度学习入门篇-Task3《深度学习详解》- 实践方法
     核心学习目标:通过《深度学习详解》和李宏毅老师21年的机器学习课程视频,入门机器学习,并尝试学习深度学习,展开代码实践(选修)。该书保留了李宏毅老师公开课中大量生动有趣的例子,帮助读者从生活化的角度理解深度学习的概念、建模过程和核心算法细节,包括卷积神经网络、Transform......
  • Vue3 官方推荐状态管理库Pinia
    介绍Pinia是Vue官方团队推荐代替Vuex的一款轻量级状态管理库,允许跨组件/页面共享状态。Pinia旨在提供一种更简洁、更直观的方式来处理应用程序的状态。Pinia充分利用了Vue3的CompositionAPI。官网:Pinia符合直觉的Vue.js状态管理库Pinia的核心概念store......
  • 比特币详解
    1.比特币的由来        自2008年中本聪引入比特币以来,比特币已经在全球范围内掀起了广泛讨论。无论褒贬如保,它是目前世界上最成功的数字货币,针对它的投资已有数十亿美元。截至2020年10月,比特币的市值约为2121亿美元。注意:        2013年12月5......