Vue组件间通信的9种实现方式

组件的通信

父子组件通信

父子组件通信可以理解成:
父组件向子组件传值。
父组件调用子组件的方法。

子组件向父组件传值。
子组件调用父组件的方法。

1.props: 利用props属性实现父组件向子组件传值。

parent.vue文件


<template><div>父组件<!-- 子组件在不同的父组件中传递 --><children data="我是父组件传递的值" ></children><children data="我是父组件传递的值" :num="18"></children></div>
</template>
<script setup lang="ts">
import children from '@/components/children.vue'
</script>

children.vue 文件

<template><div>子组件:{{data}}<div>年龄: {{num}}</div></div>
</template>
<script lang="ts">
import { defineComponent } from "vue";export default defineComponent({name: 'children',props: {data: String,num: {type: Number,default: () => 20},}
})
</script>

props不仅可以传字符串、数字、数组、对象、boolean的值,在传递时props也可以定义数据校验,以此来限制接收的数据类型等。
父传子的方式形成了一个单向下行绑定,叫做单向数据流。父级props的更新也会向下流程到接收这个props的子组件中,触发对应的更新,但是反过来则不行。如果遇到确实需要改变props值的应用场合,则采用下面的解决方法:

children.vue文件

<template><div><div>必须被修改的值第一种:  {{myData}}</div><div>必须被修改的值第二种:  {{childData}}</div></div>
</template>
<script lang="ts">
import { computed, defineComponent, ref } from "vue";export default defineComponent({name: 'children',props: {data: String,num: {type: Number,default: () => 20},},setup(props) {// 第一种const myData = ref(props.data)myData.value = '通过初始化的方式进行修改'// 第二种const childData = computed(() => {return props.data + '通过computed属性实现修改'})return {myData,childData}}
})
</script>

2. $refs: 利用$refs属性可以实现父组件调用子组件的方法。通常用于直接操作子组件,但不推荐用于数据传递。

Vue2的写法

    <refChild ref="childRef"></refChild>this.$refs.refChild?.childFn()

Vue3的写法
parent.vue文件

<template><div class="mt15">  $refs通信的子组件<refChild ref="compontentRef"></refChild></div>
</template>
<script lang="ts">
import refChild from '@/components/refChild.vue'
import { defineComponent, onMounted, ref } from 'vue'export default defineComponent({name: 'parent',components: {refChild},setup() {const compontentRef = ref(null)const getRefChild = () => {compontentRef.value?.childFn();}onMounted(() => {getRefChild();})return {compontentRef,getRefChild}}
})

refChild.vue文件

<template><div>$refs紫组件</div>
</template>
<script lang="ts">
import { defineComponent } from "vue";export default defineComponent({name: 'refChild',setup(props, context) {const childFn = () => {console.log('fn的方法被调用')}// 第一种写法context.expose({ childFn: childFn })// 第二种写法 defineExpose不需要引入,直接使用// defineExpose({ childFn: childFn })}
})
</script>

3.slot: 通过插槽实现父组件向子组件传值。关于插槽

// 父组件<div><slotChild>默认传值的方式</slotChild></div>
// 子组件
<template><div><slot></slot></div>
</template>

4.$emit: 触发当前组件实例上的事件,可以理解成子组件触发了绑定在父组件上的自定义事件。

parent.vue文件

 <children data="我是父组件传递的值" :num="18" @fromGreet="fromGreet"></children>
import { defineComponent, onMounted, ref } from 'vue'
import children from '@/components/children.vue'
import refChild from '@/components/refChild.vue'
import slotChild from '@/components/slotChild.vue'export default defineComponent({name: 'parent',components: {children,},setup() {const fromGreet = (data) => {console.log('来自子组件的调用', data)}return {fromGreet}}
})

children.vue文件

<template><div>子组件:{{data}} <a-button type="primary" @click="greet">打招呼</a-button></div>
</template>
import { computed, defineComponent, ref } from "vue";export default defineComponent({name: 'children',props: {data: String,},setup(props, context) {const greet = () => {context.emit('fromGreet', 'hello')}return {greet}}
})

5.$parent: 在子组件直接获取父组件的实例,从而调用父组件中的方法,类似于$refs获取子组件的方法。

因Vue3的组合式API设计原则,应该尽量避免直接使用$parent,可能会导致组件之间的耦合度过高。推荐下面的实现方法:

parent.vue文件

    <children @call-parent-method="toChildClick"></children>
    const toChildClick = (data) => {console.log('来自子组件的调用', data)}

children.vue文件

  <a-button danger @click="getParentFn">调用父组件的方法</a-button>
import { computed, defineComponent, ref } from "vue";export default defineComponent({name: 'children',emits: ['call-parent-method'],setup(props, context) {const getParentFn = () => {context.emit('call-parent-method');}return {getParentFn}}
})

Vue2的写法可参考$refs。

6. 事件总线EventBus/mitt实现兄弟组件通信

在Vue2中,可以采用EventBus这种方法。利用一个空的Vue实例来作为桥梁,实现事件分发,它的工作原理是发布/订阅方法,通常称为Pub/Sub,也就是发布和订阅的模式。

var bus = new Vue()// 组件A
bus.$emit('event', 'hello from component A')// 组件B
bus.$on('event', (message) => {console.log(message); // 'hello from component A'
}) 

在Vue3中,采用第三方事件总线库mitt取代了EventBus事件。mitt的使用方法和EventBus非常类似,同样是基于Pub/Sub模式,并且更加简单,可以在需要进行通信的地方直接使用。

首先需要安装:

npm install mitt

创建一个工具包 eventBus.ts

import mitt from 'mitt';
export const emitter = mitt();

在componentA组件

<a-button type="primary" @click="sendMessage">发送消息给兄弟组件</a-button>
import { emitter } from '@/utils/eventBus'
export default defineComponent({setup(props, context) {const sendMessage = () => {// 发布一个事件emitter.emit('sendMessage', 'hello from component A')}return {sendMessage}}
})

在componetB组件

<div>message from component A: {{ message }}
</div>
import { defineComponent, onMounted, onUnmounted, ref } from "vue";
import { emitter } from '@/utils/eventBus'export default defineComponent({setup(props, context) {const message = ref('')onMounted(() => {emitter.on('sendMessage', (msg) => {message.value = msg;})})onUnmounted(() => {emitter.off('sendMessage')})return {message}}
})

事件总线的方式进行通信使用起来非常简单,可以实现任意组件之间的通信,其中没有多余的业务逻辑,只需要在状态变化组件触发一个事件,随后在处理逻辑组件监听该事件即可。

7. provide/inject AP实现跨级组件

provide/inject是一种跨组件传递数据的方式,允许祖先组件向其所有子孙后代注入依赖,而不必一层层地通过props传递。

import { defineComponent, provide, ref } from 'vue'
export default defineComponent({setup(props, context) {const theme = ref('dark')provide('theme', theme)}
})
<div>主题: {{ theme }}
</div>
import { defineComponent, ref, inject } from "vue";export default defineComponent({setup(props, context) {const theme = inject('theme')return {theme}}
})

8.vuex状态管理

对于一些大型的项目,要实现复杂的组件通信和状态管理。
组合式API的写法

import { createStore } from 'vuex'export default createStore({state: {message: 'vue'},mutations: {UPDATE_MESSAGE(state, newMessage) {state.message = newMessage},},actions: {updateMessage({ commit }, message) {commit('UPDATE_MESSAGE', message)},},getters: {message: state => state.message;}
})// 在组件中获取信息
const store = useStore()const message = computed(() => store.getters.message)const updateMessage = () => {store.dispatch('updateMessage','New Message')
}

9.pinia状态管理

Pinia主打简单和轻量,其大小仅有1KB。
组合式API写法

import { ref, computed } from 'vue'
import { defineStore } from 'pinia'export const useCounterStore = defineStore('counter', () => {const count = ref(0)const doubleCount = computed(() => count.value * 2)const increment = () => {count.value++}return { count, doubleCount, increment }
})// 在文件中引入
import { useCounterStore } from '@/stores/counter'export default defineComponent({setup() {const counter = useCounterStore()counter.count++;// 两种写法// 第一种counter.$patch({ count: counter.count + 1})// 第二种counter.increment();}
})

前3种解释了父组件向子组件传值的不同写法,4,5解释了子组件向父组件传值及调用方法。6解释了兄弟组件之间的通信,7解释了不同组件之间通信,8,9状态管理适合用于大型应用,组件众多,状态零散地分布在需要组件和组件之间的交互操作中,复杂度也不断增长的项目。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/58197.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

jmeter脚本-请求体设置变量and请求体太长的处理

目录 1、查询接口 1.1 准备组织列表的TXT文件&#xff0c;如下&#xff1a; 1.2 添加 CSV数据文件设置 &#xff0c;如下&#xff1a; 1.3 接口请求体设置变量&#xff0c;如下&#xff1a; 2、创建接口 2.1 见1.1 2.2 见1.2 2.3 准备创建接口的请求体TXT文件&#xff…

SQL,力扣题目1549,每件商品的最新订单【窗口函数】

一、力扣链接 LeetCode_1549 二、题目描述 表: Customers ------------------------ | Column Name | Type | ------------------------ | customer_id | int | | name | varchar | ------------------------ customer_id 是该表主键. 该表包含消费者的…

函数指针和指针函数的区别

函数指针和指针函数是 C 语言中两个重要的概念&#xff0c;它们在功能和用途上有显著区别。下面将详细解释这两者的含义、用法以及各自的示例。 一、定义 函数指针&#xff08;Function Pointer&#xff09;&#xff1a; 函数指针是指向函数的指针。通过函数指针&#xff0c;可…

【网络】HTTP(超文本传输协议)详解

目录 引言一、HTTP的基本概念1.1 什么是HTTP&#xff1f;1.2 HTTP的工作流程1.3 HTTP工作流程图 二、HTTP请求与响应2.1 HTTP请求格式2.2 HTTP响应格式 三、常见的HTTP状态码3.1 其他状态码示例 四、HTTP版本的演变4.1 HTTP/1.04.2 HTTP/1.14.3 HTTP/24.4 HTTP/3 五、HTTP的安全…

卸载 Adobe Genuine Software Client

一、问题描述 使用破jie版Adobe Acrobat Pro DC软件后&#xff0c;会经常弹出以下窗口&#xff1a; 且上述探窗无法直接关掉。即使通过任务管理器将其临时关掉&#xff0c;可等过一段时间后&#xff0c;仍然会再次弹出&#xff0c;严重干扰工作进度。 二、问题解决 &#xff…

点云从入门到精通技术详解100篇-基于结构光测量的三维人脸重建及识别

目录 前言 三维人脸识别技术国内外现状 二维人脸识别研究现状 三维测量技术研究现状 三维人脸识别研究现状 2三维人脸重建及识别系统方案 2.1 基于结构光的三维人脸重建及识别系统构成 2.1.1 典型的投影光栅相位测量几何模型 2.1.1.1 平行式投影系统 2.1.1.2 交叉…

京东云雅典娜刷机步骤(需要拆机)

京东云雅典娜刷机步骤 必须拆机 必须拆机 必须拆机 刷机要用的文件 1.高通驱动文件&#xff08;USB刷机必备&#xff09;&#xff1a;https://pan.quark.cn/s/6405674f981b 2.进入临时uboot的程序&#xff1a;https://pan.quark.cn/s/ebc1d449cb89 3.uboot固件&#xff1a; ht…

电子商城购物平台的设计与开发+ssm(lw+演示+源码+运行)

摘 要 随着我国经济迅速发展&#xff0c;人们对手机的需求越来越大&#xff0c;各种手机软件也都在被广泛应用&#xff0c;但是对于手机进行数据信息管理&#xff0c;对于手机的各种软件也是备受用户的喜爱&#xff0c;电子商城购物平台小程序被用户普遍使用&#xff0c;为方便…

基于 Spring Boot 和 Vue 的门票销售创新系统

作者介绍&#xff1a;✌️大厂全栈码农|毕设实战开发&#xff0c;专注于大学生项目实战开发、讲解和毕业答疑辅导。 &#x1f345;获取源码联系方式请查看文末&#x1f345; 推荐订阅精彩专栏 &#x1f447;&#x1f3fb; 避免错过下次更新 Springboot项目精选实战案例 更多项目…

【Python】Python自习课:第一个python程序

【Python】Python自习课&#xff1a;第一个python程序 示例

docker-compose安装rabbitmq 并开启延迟队列和管理面板插件(rabbitmq_delayed_message_exchange)

问题&#xff1a; 解决rabbitmq-plugins enable rabbitmq_delayed_message_exchange &#xff1a;plugins_not_found 我是在docker-compose环境部署的 services:rabbitmq:image: rabbitmq:4.0-managementrestart: alwayscontainer_name: rabbitmqports:- 5672:5672- 15672:156…

103 - Lecture 2 Table and Data Part 1

SQL - Tables and Data Part 1 Relational Database Management System(RDBMS) 关系型数据库管理系统&#xff08;RDBMS&#xff09;是基于关系模型的数据库系统&#xff0c;它支持多种关系操作。关系模型是一种数据存储和检索的模型&#xff0c;它使用表格来组织数据&#x…

Linux云计算个人学习总结(二)

高级文件系统 一、RSYNC概述 1、作用&#xff1a;快速的文件复制工具&#xff08;支持本地和远程&#xff09;&#xff0c;以及删除、查看等基本功能。 2、特点&#xff1a;支持实时&#xff08;inotify、sersync&#xff09;的增量备份工具3、模式&#xff1a;检查模式&#…

PropTypes 和 TypeScript 在 React 中的比较

文章目录 引言PropTypes什么是 PropTypes&#xff1f;如何使用 PropTypes优点缺点 TypeScript什么是 TypeScript&#xff1f;如何使用 TypeScript优点缺点 选择建议总结 引言 在 React 开发中&#xff0c;组件的可复用性和可维护性至关重要。为了确保组件接收到正确的 props&a…

CommunityToolkit.Mvvm如何使用

CommunityToolkit.Mvvm 是一个现代、快速和模块化的 MVVM 库&#xff0c;用于 .NET 应用程序。以下是如何使用 CommunityToolkit.Mvvm 的基本步骤&#xff1a; 安装包&#xff1a; 你可以通过 NuGet 包管理器安装 CommunityToolkit.Mvvm。在 Visual Studio 中&#xff0c;你可以…

【自动化利器】12个评估大语言模型(LLM)质量的自动化框架

LLM评估是指在人工智能系统中评估和改进语言和语言模型的过程。在人工智能领域&#xff0c;特别是在自然语言处理&#xff08;NLP&#xff09;及相关领域&#xff0c;LLM评估具有至高无上的地位。通过评估语言生成和理解模型&#xff0c;LLM评估有助于细化人工智能驱动的语言相…

mybatis源码解析-sql执行流程

1 执行器的创建 1. SimpleExecutor 描述&#xff1a;最基本的执行器&#xff0c;每次查询都会创建新的语句对象&#xff0c;并且不会缓存任何结果。 特点&#xff1a; 每次查询都会创建新的 PreparedStatement 对象。 不支持一级缓存。 适用于简单的查询操作&#xff0c;不…

儿童安全座椅行业全面深入分析

儿童安全座椅就是一种专为不同体重&#xff08;或年龄段&#xff09;的儿童设计&#xff0c;将孩子束缚在安全座椅内&#xff0c;能有效提高儿童乘车安全的座椅。欧洲强制性执行标准ECE R44/03的定义是&#xff1a;能够固定到机动车辆上&#xff0c;带有ISOFIX接口、LATCH接口的…

【React 的理解】

谈一谈你对 React 的理解 对待这类概念题&#xff0c;讲究一个四字口诀“概用思优”&#xff0c;即“讲概念&#xff0c;说用途&#xff0c;理思路&#xff0c;优缺点&#xff0c;列一遍” 。 React 是一个网页 UI 框架&#xff0c;通过组件化的方式解决视图层开发复用的问题&a…

对象的接口与设计模式在其中的作用

对象的接口 对象的接口定义了对象的行为和如何与外界进行交互。以下是对象接口的详细解释&#xff1a; 成员函数&#xff08;Member Functions&#xff09; 定义&#xff1a;成员函数是定义在类中的函数&#xff0c;用于实现类的行为。成员函数可以通过对象来调用&#xff0…