Toggle navigation
首页
产品中心
全新RDIF.vNext低代码框架
镇店
.NET C/S开发框架
.NET Web敏捷开发框架
.NET 快速开发框架(全新EasyUI版本)
.NET 代码生成器
.NET WebAPI服务端开发框架
客户案例
付款方式
国思学堂
技术文章
新闻资讯
下载
关于
首页
技术文章
前端技术
正文
原创
2024-06-26
浏览 (
5973
)
【干货】Vue3 组件通信方式详解
## 前言 毫无疑问,组件通信是Vue中非常重要的技术之一,它的出现能够使我们非常方便的在不同组件之间进行数据的传递,以达到数据交互的效果。所以,学习组件通信技术是非常有必要的,本文将总结Vue中关于组件通信的八种方式,帮助大家在使用Vue的过程中更加得心应手! 如果文中有不对、疑惑的地方,欢迎在评论区留言指正!! ## 一、什么是组件通信 在开始之前我们需要明白什么是组件通信,**组件通信**可以拆分为两个部分: - 组件 - 通信 都知道组件是`vue`最强大的功能之一,`vue`中每一个`.vue`文件我们都可以视之为一个组件,简单来说组件就是对UI结构的复用。 通信指的是发送者通过某种媒体以某种格式来传递信息到收信者以达到某个目的。广义上,任何信息的交通都是通信。而**组件间通信**即指组件(`.vue`)通过某种方式来传递信息以达到某个目的,举个栗子我们在使用`UI`框架中的`table`组件,可能会往`table`组件中传入某些数据,这个本质就形成了组件之间的通信 ## 二、为什么要进行组件通信 通信的本质是信息同步,共享。回到vue中,每个组件之间的都有独自的作用域,组件间的数据是无法共享的但实际开发工作中我们常常需要让组件之间共享数据,这也是组件通信的目的要让它们互相之间能进行通讯,这样才能实现数据间的交互,完成某种功能的开发。 ## 三、组件通信的分类 组件间通信的分类可以分成以下 - 父子组件之间的通信 - 兄弟组件之间的通信 - 祖孙与后代组件之间的通信 - 非关系组件间之间的通信 他们之间的关系如下图: ![组件](http://doc.rdiframework.net/rdiblog/20230426111645.png) 目前最常用是`props/$emit` 和 `vuex/pinia` ,接下来是 `provide/inject`,其他不建议使用; 实际项目中,简单父子组件传递采用`props/$emit` ,涉及全局共享的数据一般采用 `vuex/pinia` 结合存储对象`localStorage/sessionStorage`使用。 ![Vue3 组件通信方式](http://doc.rdiframework.net/rdiblog/20230426111409.png) ## 四、Vue3 的八种组件通信方式 - props - $emit - expose / ref - $attrs - v-model - provide / inject - Vuex - mitt ## 五、Vue3 八种通信方式用法讲解 ### 1. props 用 props 传数据给子组件有两种方法,如下 方法一,setup() 方法写法 ```js // 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 语法糖 ```js // 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 ```js // 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 父组件获取子组件的属性或者调用子组件方法。 ```js // 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 **属性集合**。 ```js // 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 可以支持多个数据双向绑定 ```js // 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`:在任何后代组件中接收想要添加在这个组件上的数据,不管组件嵌套多深都可以直接拿来用 ```js // 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 ```js // 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) // 1 const count = computed(()=>store.state.count) // 响应式,会随着vuex数据改变而改变 console.log(count) // 1 </script> ``` ### 8. mitt Vue3 中没有了 EventBus 跨组件通信,但是现在有了一个替代的方案 mitt.js,原理还是 EventBus。 先安装 `npm i mitt -S` 然后像以前封装 bus 一样,封装一下 ```js mitt.js import mitt from 'mitt' const mitt = mitt() export default mitt ``` 然后两个组件之间通信的使用 ```js // 组件 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/](https://cn.vuejs.org/) vuex是什么:[https://vuex.vuejs.org/zh/](https://vuex.vuejs.org/zh/) 工作中要使用Git,看这篇文章就够了:[http://www.guosisoft.com/article/detail/410508049313861](http://www.guosisoft.com/article/detail/410508049313861) 企业数字化转型如何做?看过来:[http://www.guosisoft.com/article/detail/408745545576517](http://www.guosisoft.com/article/detail/408745545576517) Vue2.x 组件通信方式:[http://www.guosisoft.com/article/detail/411234710110277](http://www.guosisoft.com/article/detail/411234710110277) 【保姆级教程】Vue项目调试技巧:[http://www.guosisoft.com/article/detail/430312211521605](http://www.guosisoft.com/article/detail/430312211521605) Vue 前端开发团队风格指南(史上最全):[http://www.guosisoft.com/article/detail/415491255230533](http://www.guosisoft.com/article/detail/415491255230533) 国思RDIF低代码快速开发平台(支持vue2、vue3):[http://www.guosisoft.com/article/detail/557095625134149](http://www.guosisoft.com/article/detail/557095625134149) ## 七、结语 如果本文对你有一点点帮助,点个赞支持一下吧,你的每一个【赞】都是我创作的最大动力 ^_^ 更多技术文章请往: [http://www.guosisoft.com/article](http://www.guosisoft.com/article) [http://www.rdiframework.net/article](http://www.rdiframework.net/article) 大家一起共同交流和进步呀!! ----- 一路走来数个年头,感谢RDIF框架的支持者与使用者,大家可以通过下面的地址了解详情。 官方网站:[http://www.guosisoft.com/](http://www.guosisoft.com/) [http://www.rdiframework.net/](http://www.rdiframework.net/) 特别说明,框架相关的技术文章请以官方网站为准,欢迎大家收藏! **国思RDIF低代码快速开发框架**由海南国思软件科技有限公司专业团队长期打造、一直在更新、一直在升级,请放心使用! 欢迎关注国思RDI低代码快速开发框架官方公众微信(微信号:guosisoft),及时了解最新动态。 使用微信扫描二维码立即关注 ![微信扫描二维码](http://doc.rdiframework.net/weixin.png )
正文到此结束
本文标签:
挨踢业界
RDIF.NET
Web前端
版权声明:
本站原创文章,由
guosisoft.com
发布,遵循
CC 4.0 by-sa
版权协议,转载请附上原文出处链接和本声明。
上一篇
玩转数据库索引
下一篇
国思RDIF-Wms仓储管理系统助力企业高效数字化(源码交付)
热门推荐
{{article.title}}
热门指数:
浏览({{article.lookCount + 5000}})
相关文章
{{article.title}}
该篇文章的评论功能暂时被站长关闭
说给你听
本文目录
文章标签
RDIF.NET
其他
微信开发
.NET
消息交互
.NetCore
项目管理
常用工具
工作流
Web前端
数据库
挨踢业界
随机文章
RDIFramework.NET(.NET快速开发框架) 答客户问(2014-02-23)
[推荐]ORACLE SQL:经典查询练手第三篇(不懂装懂,永世饭桶!)
ORACLE常见问题一千问[201至300](不怕学不成、就怕心不诚!)
微信公众号开发C#系列-8、自定义菜单及菜单响应事件的处理
RDIFramework.NET V3.3 Web版新增日程管理功能模块
JSON风格指南-真经
.NET Core部署到linux(CentOS)最全解决方案,进阶篇(Supervisor+Nginx)
.NET快速信息化系统开发框架 V3.2 -> “用户管理”主界面使用多表头展示、增加打印功能
.NET Core部署到linux(CentOS)最全解决方案,常规篇
国思RDIF-Wms仓储管理系统助力企业高效数字化(源码交付)
.NET快速信息化系统开发框架 V3.2 -> WinForm“组织机构管理”界面组织机构权限管理采用新的界面,操作权限按模块进行展示
ORACLE常见问题一千问[101至200](不怕学不成、就怕心不诚!)
RDIFramework.NET V3.3 Web框架主界面新增横向菜单功能
.NET Core部署到linux(CentOS)最全解决方案,高阶篇(Docker+Nginx 或 Jexus)
RDIFramework.NET CS敏捷开发框架 SOA服务三种访问(直连、WCF、WebAPI)方式
一文搞懂flex(弹性盒布局)
ORACLE常见问题一千问[601至700](不怕学不成、就怕心不诚!)
ORACLE常见问题一千问(提供下载)(不怕学不成、就怕心不诚!)
Win10年度更新开发必备:VS2015 Update 3正式版下载汇总
RDIFramework.NET Web版报表管理-助力企业高效智能图表
网站信息
文章总数:599 篇
标签总数:8 个
分类总数:8 个
留言数量:1385 条
在线人数:
89
人
运行天数:1321天
最后更新:2023-05-18
QQ:406590790
13005007127