【干货】Vue3 组件通信方式详解

前言

毫无疑问,组件通信是Vue中非常重要的技术之一,它的出现能够使我们非常方便的在不同组件之间进行数据的传递,以达到数据交互的效果。所以,学习组件通信技术是非常有必要的,本文将总结Vue中关于组件通信的八种方式,帮助大家在使用Vue的过程中更加得心应手!

如果文中有不对、疑惑的地方,欢迎在评论区留言指正!!

一、什么是组件通信

在开始之前我们需要明白什么是组件通信,组件通信可以拆分为两个部分:

  • 组件
  • 通信

都知道组件是vue最强大的功能之一,vue中每一个.vue文件我们都可以视之为一个组件,简单来说组件就是对UI结构的复用。

通信指的是发送者通过某种媒体以某种格式来传递信息到收信者以达到某个目的。广义上,任何信息的交通都是通信。而组件间通信即指组件(.vue)通过某种方式来传递信息以达到某个目的,举个栗子我们在使用UI框架中的table组件,可能会往table组件中传入某些数据,这个本质就形成了组件之间的通信

二、为什么要进行组件通信

通信的本质是信息同步,共享。回到vue中,每个组件之间的都有独自的作用域,组件间的数据是无法共享的但实际开发工作中我们常常需要让组件之间共享数据,这也是组件通信的目的要让它们互相之间能进行通讯,这样才能实现数据间的交互,完成某种功能的开发。

三、组件通信的分类

组件间通信的分类可以分成以下

  • 父子组件之间的通信
  • 兄弟组件之间的通信
  • 祖孙与后代组件之间的通信
  • 非关系组件间之间的通信

他们之间的关系如下图:

组件

目前最常用是props/$emitvuex/pinia ,接下来是 provide/inject,其他不建议使用;
实际项目中,简单父子组件传递采用props/$emit ,涉及全局共享的数据一般采用 vuex/pinia 结合存储对象localStorage/sessionStorage使用。

Vue3 组件通信方式

四、Vue3 的八种组件通信方式

  • props
  • $emit
  • expose / ref
  • $attrs
  • v-model
  • provide / inject
  • Vuex
  • mitt

五、Vue3 八种通信方式用法讲解

1. props

用 props 传数据给子组件有两种方法,如下

方法一,setup() 方法写法

// Parent.vue 传送
<child :msg1="msg1" :msg2="msg2"></child>
<script>
import child from "./child.vue"
import { ref, reactive } from "vue"
export default {data(){return {msg1:"这是传级子组件的信息1"}},setup(){// 创建一个响应式数据// 写法一 适用于基础类型  ref 还有其他用处,下面章节有介绍const msg2 = ref("这是传级子组件的信息2")// 写法二 适用于复杂类型,如数组、对象const msg2 = reactive(["这是传级子组件的信息2"])return {msg2}}
}
</script>// Child.vue 接收
<script>
export default {props: ["msg1", "msg2"],// 如果这行不写,下面就接收不到setup(props) {console.log(props) // { msg1:"这是传给子组件的信息1", msg2:"这是传给子组件的信息2" }},
}
</script>

方法二,setup 语法糖

// Parent.vue 传送
<child :msg2="msg2"></child>
<script setup>import child from "./child.vue"import { ref, reactive } from "vue"const msg2 = ref("这是传给子组件的信息2")// 或者复杂类型const msg2 = reactive(["这是传级子组件的信息2"])
</script>// Child.vue 接收
<script setup>// 不需要引入 直接使用// import { defineProps } from "vue"const props = defineProps({// 写法一msg2: String// 写法二msg2:{type:String,default:""}})console.log(props) // { msg2:"这是传级子组件的信息2" }
</script>

注意:

如果父组件是setup(),子组件setup 语法糖写法的话,是接收不到父组件里 data 的属性,只能接收到父组件里 setup 函数里传的属性。

如果父组件是setup 语法糖写法,子组件setup()方法写法,可以通过 props 接收到 data 和 setup 函数里的属性,但是子组件要是在 setup 里接收,同样只能接收到父组件中 setup 函数里的属性,接收不到 data 里的属性

官方也说了,既然用了 3,就不要写 2 了,所以不推荐setup()方法写法。下面的例子,一律只用语法糖的写法。

2. $emit

// Child.vue 派发
<template>// 写法一<button @click="emit('myClick')">按钮</buttom>// 写法二<button @click="handleClick">按钮</buttom>
</template>
<script setup>// 方法一 适用于Vue3.2版本 不需要引入// import { defineEmits } from "vue"// 对应写法一const emit = defineEmits(["myClick","myClick2"])// 对应写法二const handleClick = ()=>{emit("myClick", "这是发送给父组件的信息")}// 方法二 不适用于 Vue3.2版本,该版本 useContext()已废弃import { useContext } from "vue"const { emit } = useContext()const handleClick = ()=>{emit("myClick", "这是发送给父组件的信息")}
</script>// Parent.vue 响应
<template><child @myClick="onMyClick"></child>
</template>
<script setup>import child from "./child.vue"const onMyClick = (msg) => {console.log(msg) // 这是父组件收到的信息}
</script>

3. expose / ref

父组件获取子组件的属性或者调用子组件方法。

// Child.vue
<script setup>// 方法一 不适用于Vue3.2版本,该版本 useContext()已废弃import { useContext } from "vue"const ctx = useContext()// 对外暴露属性方法等都可以ctx.expose({childName: "这是子组件的属性",someMethod(){console.log("这是子组件的方法")}})// 方法二 适用于Vue3.2版本, 不需要引入// import { defineExpose } from "vue"defineExpose({childName: "这是子组件的属性",someMethod(){console.log("这是子组件的方法")}})
</script>// Parent.vue  注意 ref="comp"
<template><child ref="comp"></child><button @click="handlerClick">按钮</button>
</template>
<script setup>import child from "./child.vue"import { ref } from "vue"const comp = ref(null)const handlerClick = () => {console.log(comp.value.childName) // 获取子组件对外暴露的属性comp.value.someMethod() // 调用子组件对外暴露的方法}
</script>

4. attrs

attrs:包含父作用域里除 class 和 style 除外的非 props 属性集合

// Parent.vue 传送
<child :msg1="msg1" :msg2="msg2" title="3333"></child>
<script setup>import child from "./child.vue"import { ref, reactive } from "vue"const msg1 = ref("1111")const msg2 = ref("2222")
</script>// Child.vue 接收
<script setup>import { defineProps, useContext, useAttrs } from "vue"// 3.2版本不需要引入 defineProps,直接用const props = defineProps({msg1: String})// 方法一 不适用于 Vue3.2版本,该版本 useContext()已废弃const ctx = useContext()// 如果没有用 props 接收 msg1 的话就是 { msg1: "1111", msg2:"2222", title: "3333" }console.log(ctx.attrs) // { msg2:"2222", title: "3333" }// 方法二 适用于 Vue3.2版本const attrs = useAttrs()console.log(attrs) // { msg2:"2222", title: "3333" }
</script>

5. v-model

可以支持多个数据双向绑定

// Parent.vue
<child v-model:key="key" v-model:value="value"></child>
<script setup>import child from "./child.vue"import { ref, reactive } from "vue"const key = ref("1111")const value = ref("2222")
</script>// Child.vue
<template><button @click="handlerClick">按钮</button>
</template>
<script setup>// 方法一  不适用于 Vue3.2版本,该版本 useContext()已废弃import { useContext } from "vue"const { emit } = useContext()// 方法二 适用于 Vue3.2版本,不需要引入// import { defineEmits } from "vue"const emit = defineEmits(["key","value"])// 用法const handlerClick = () => {emit("update:key", "新的key")emit("update:value", "新的value")}
</script>

6. provide / inject

provide / inject 为依赖注入

provide:可以让我们指定想要提供给后代组件的数据或

inject:在任何后代组件中接收想要添加在这个组件上的数据,不管组件嵌套多深都可以直接拿来用

// Parent.vue
<script setup>import { provide } from "vue"provide("name", "RDIF")
</script>// Child.vue
<script setup>import { inject } from "vue"const name = inject("name")console.log(name) // RDIF
</script>

7. Vuex

// store/index.js
import { createStore } from "vuex"
export default createStore({state:{ count: 1 },getters:{getCount: state => state.count},mutations:{add(state){state.count++}}
})// main.js
import { createApp } from "vue"
import App from "./App.vue"
import store from "./store"
createApp(App).use(store).mount("#app")// Page.vue
// 方法一 直接使用
<template><div>{{ $store.state.count }}</div><button @click="$store.commit('add')">按钮</button>
</template>// 方法二 获取
<script setup>import { useStore, computed } from "vuex"const store = useStore()console.log(store.state.count) // 1const count = computed(()=>store.state.count) // 响应式,会随着vuex数据改变而改变console.log(count) // 1 
</script>

8. mitt

Vue3 中没有了 EventBus 跨组件通信,但是现在有了一个替代的方案 mitt.js,原理还是 EventBus。

先安装 npm i mitt -S

然后像以前封装 bus 一样,封装一下

mitt.js
import mitt from 'mitt'
const mitt = mitt()
export default mitt

然后两个组件之间通信的使用

// 组件 A
<script setup>
import mitt from './mitt'
const handleClick = () => {mitt.emit('handleChange')
}
</script>// 组件 B 
<script setup>
import mitt from './mitt'
import { onUnmounted } from 'vue'
const someMethed = () => { ... }
mitt.on('handleChange',someMethed)
onUnmounted(()=>{mitt.off('handleChange',someMethed)
})
</script>

六、参考资料

vue.js: https://cn.vuejs.org/

vuex是什么:https://vuex.vuejs.org/zh/

工作中要使用Git,看这篇文章就够了:http://www.guosisoft.com/article/detail/410508049313861

企业数字化转型如何做?看过来:http://www.guosisoft.com/article/detail/408745545576517

【保姆级教程】Vue项目调试技巧:http://www.guosisoft.com/article/detail/430312211521605

Vue2.x 组件通信方式:http://www.guosisoft.com/article/detail/411234710110277

Vue 前端开发团队风格指南(史上最全):http://www.guosisoft.com/article/detail/415491255230533

国思RDIF低代码快速开发平台(支持vue2、vue3):http://www.guosisoft.com/article/detail/557095625134149

七、结语

如果本文对你有一点点帮助,点个赞支持一下吧,你的每一个【赞】都是我创作的最大动力 _

更多技术文章请往:http://www.guosisoft.com/article,大家一起共同交流和进步呀


一路走来数个年头,感谢RDIF框架的支持者与使用者,大家可以通过下面的地址了解详情。

官方网站:http://www.guosisoft.com/ http://www.rdiframework.net/

特别说明,框架相关的技术文章请以官方网站为准,欢迎大家收藏!

国思RDIF低代码快速开发框架由海南国思软件科技有限公司专业团队长期打造、一直在更新、一直在升级,请放心使用!

欢迎关注国思RDI低代码快速开发框架官方公众微信(微信号:guosisoft),及时了解最新动态。

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

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

相关文章

【博士每天一篇文献-算法】Fearnet Brain-inspired model for incremental learning

阅读时间&#xff1a;2023-12-16 1 介绍 年份&#xff1a;2017 作者&#xff1a;Ronald Kemker&#xff0c;美国太空部队&#xff1b;Christopher Kanan&#xff0c;罗切斯特大学 期刊&#xff1a; arXiv preprint 引用量&#xff1a;520 Kemker R, Kanan C. Fearnet: Brain-…

宠物领养救助管理系带万字文档java项目基于springboot+vue的宠物管理系统java课程设计java毕业设计

文章目录 宠物领养救助管理系统一、项目演示二、项目介绍三、万字项目文档四、部分功能截图五、部分代码展示六、底部获取项目源码带万字文档&#xff08;9.9&#xffe5;带走&#xff09; 宠物领养救助管理系统 一、项目演示 宠物领养救助系统 二、项目介绍 基于springbootv…

WEB与低代码:B/S架构在开发中的应用与优势

在互联网迅猛发展的今天&#xff0c;WEB应用已经成为人们日常生活和工作中不可或缺的一部分。随着技术的进步和需求的多样化&#xff0c;开发高效、灵活且易于维护的WEB应用变得尤为重要。B/S架构&#xff08;Browser/Server Architecture&#xff09;作为一种常见的WEB应用架构…

Chatopera 云服务实现类海尔服务智能客服的功能点比较 | Chatopera

在上一篇文章中&#xff0c;我分享了《智能客服体验分析&#xff0c;使用小程序海尔服务完成电器报修》。如果使用 Chatopera 云服务实现一个类似的应用&#xff0c;如何做呢&#xff1f;借助 Chatopera 云服务 可以实现一个智能客服&#xff0c;那么和现在的海尔服务小程序会有…

WordPress软件下载主题Inpandora

Inpandora&#xff08;中文名为潘多拉&#xff09;是一款基于软件下载站定制的WordPress主题&#xff0c;帮助站长使用WordPress快速搭建一个专业的WordPress软件博客。Inpandora这款WordPress主题可以说是因软件而生&#xff0c;从UI设计到后台设置功能&#xff0c;都充分体现…

云计算运维工程师的突发状况处理

云计算运维工程师在应对突发的故障和紧急情况时,需要采取一系列迅速而有效的措施来最小化服务中断的时间并恢复系统的稳定性。 以下是一些关键步骤和策略: 快速响应: 立即识别并确认故障的性质和范围。通知团队成员和相关的利益相关者,确保所有人了解当前情况。故障诊断:…

MD5加密接口

签名算法 app_key和app_secret由对方系统提供 MD5_CALCULATE_HASH_FOR_CHAR&#xff08;中文加密与JAVA不一致&#xff09; 代码&#xff1a; *获取传输字段名的ASCII码&#xff0c;根据ASCII码对字段名进行排序SELECT * FROM zthr0051WHERE functionid iv_functionidINTO …

想布局短视频赛道,云微客AI矩阵系统告诉你诀窍

随着人工智能技术的不断发展&#xff0c;越来越多的企业和个人创作者开始意识到智能化的重要性。而现阶段&#xff0c;随着短视频市场的膨胀扩大&#xff0c;批量成片、智能创作、定时发布是当下重要的趋势&#xff0c;企业如果想在短视频赛道分一杯羹&#xff0c;智能化的平台…

首次30米空间分辨率生成中国年度耕地栅格数据1986-2021

中国1986-2021年30米分辨率年度耕地数据集 数据介绍 精确、详细且及时的耕地范围信息对于粮食安全保障和环境可持续性至关重要。然而&#xff0c;由于农业景观的复杂性和足够训练样本的缺乏&#xff0c;在大范围下进行高时空分辨率的耕地动态监测仍然具有挑战性&#xff0c;尤其…

kafka进阶核心原理详解:案例解析(第11天)

系列文章目录 kafka高级&#xff08;重点&#xff09; kafka核心概念汇总 kafka的数据位移offset Kafka的基准/压力测试 Kafka的分片副本机制 kafka如何保证数据不丢失 kafka的消息存储及查询机制 生产者数据分发策略 消费者负载均衡机制 kafka的监控工具:kafka-eagle…

台灯学生用哪个牌子最好?五款学生专用台灯大全分享

随着科技的持续进步&#xff0c;电子产品无疑为我们的生活带来了极大的便利&#xff0c;同时也暗藏了不少隐患。其中最令广大家长忧心的便是孩子视力的健康&#xff0c;他们从小就面临着手机和电视等屏幕对孩子视力的潜在威胁。为了应对这一问题&#xff0c;家长们不遗余力地寻…

Python:基于TSFEL库对时间序列进行特征分析

1. TSFEL 时间序列作为主要TSFEL提取方法的输入传递&#xff0c;要么作为先前加载在内存中的数组传递&#xff0c;要么存储在数据集中的文件中。 由于TSFEL可以处理多维时间序列&#xff0c;因此随后应用了一套预处理方法&#xff0c;以确保信号质量足够和时间序列同步&#xf…

Linux上搭建邮件服务

欢迎来到我的博客&#xff0c;代码的世界里&#xff0c;每一行都是一个故事 &#x1f38f;&#xff1a;你只管努力&#xff0c;剩下的交给时间 &#x1f3e0; &#xff1a;小破站 Linux上搭建邮件服务 前言电子邮件的工作原理和基本组成部分1. 电子邮件的工作原理2. 电子邮件的…

Redis-实战篇-缓存雪崩

文章目录 1、缓存雪崩2、解决方案&#xff1a; 1、缓存雪崩 缓存雪崩是指在同一时段大量的缓存key同时失效或者Redis服务宕机&#xff0c;导致大量请求到达数据库&#xff0c;带来巨大压力。 2、解决方案&#xff1a; 给不同的key的TTL添加随机值利用Redis集群提高服务的可用性…

Git->git pull 和 git pull --rebase的详解

Git拉取代码的坑 格式&#xff1a;git xx指令 origin/远程仓库分支名称假如本地仓库和远程仓库都是空的 本地仓库向远程仓库提交一个文件 git commit -a -m "local first commit"&#xff1a;-a暂存修改文件到暂存区&#xff0c;准备本地提交。-m表示提交信息git pu…

Jackson和fastjson解决序列化时字段属性大小写改变的问题

在部分特殊场景下&#xff0c;我们可能会把实体的字段属性改成全部大写&#xff0c;但是在返回前端时&#xff0c;字段会被序列化成小写。 比如我们有一个这个类属性都是大写&#xff1a; 后端接口是这样的 然后我们请求后&#xff0c;会发现我们的字段被变成全部小写的。 …

jenkins环境搭建--关于jenkins在Ubuntu下的安装篇(一)

在ubuntu下使用命令进行下载安装包&#xff1a; 关于jenkins的安装有多种&#xff0c;可以借助docker容器进行安装&#xff0c;也可以通过传统方法手动一步步的进行安装&#xff0c;以下介绍手动一步步的安装方法&#xff0c;后续我们将解释关于jenkins的相关配置以及实战使用…

VCS编译bug汇总

‘typedef’ is not expected to be used in this contex 注册前少了分号。 Scope resolution error resolution : 声明指针时 不能与类名同名&#xff0c;即 不能声明为adapter. cannot find member "type_id" 忘记注册了 拼接运算符使用 关键要加上1b&#xff0…

Arduino - MG996R

Arduino - MG996R In this tutorial, we are going to learn how to use the MG996R high-torque servo motor with Arduino. 在本教程中&#xff0c;我们将学习如何将MG996R高扭矩伺服电机与Arduino一起使用。 Hardware Required 所需硬件 1Arduino UNO or Genuino UNO Ard…

WPF 深入理解六、ControlTemplate控件模板

ControlTemplate 定义 控件模板用于来定义控件的外观、样式&#xff0c;还可通过控件模板的触发器(ControlTemplate.Triggers)修改控件的行为、响应动画等。 对与WPF当中,每个控件都是无外观的,这意味着我们可以完全自定义其可视元素的外观,但是不能修改其内部的行为&#xf…