Vue3 组件通信全解析:14 种方式助力前端开发
笔记哥 /
05-09 /
28点赞 /
0评论 /
265阅读
对于日常使用`vue3`开发项目的前端小伙伴来说,`组件通信方式`可以说是必会的基本功,今天带大家一起盘下`vue3`的通信方式。
我们这里按照`组件的关系`来划分。总共包含`14中组件通信方式`。
- 一、父子通信
1. `props`
2. `defineEmits`
3. `$attrs`
4. `$ref + defineExpose`
5. `$parent`
6. `作用域插槽`
7. `v-model`
- 二、兄弟组件通信
1. `mitt`
2. `$parent`
3. `vuex/pinia`
4. `app.config.globalProperties`
- 三、跨层级通信
1. `mitt`
2. `vuex/pinia`
3. `provide/inject`
- 四:其它方式
- 浏览器本地存储`storage`
- 全局`window`对象
- ES6模块化import/export
## 一:父子通信
### 1.1、父传子:props
最最常用的通信方式是`props`了,父组件通过`props`方式将属性传递给子组件,子组件接受`props`并用于数据操作和页面渲染。
> 注意:子组件不要直接修改父组件传递过来的props,保持自上而下单项数据流,这样会让数据的流向十分清晰,方便后续维护!
```text
// Parent.vue
// Child.vue
```
> 注意:在vue3中`$listeners`已废弃,无法使用。
### 1.4、$ref + defineExpose
通过`$ref`可以拿到组件的实例,`defineExpose`可以显式指定在 `
```
1. 在父组件中通过`ref`拿到组件实例并调用子组件暴露的`update`方法。
```text
// Parent.vue
```
子组件可以在`slot`标签上传递数据给父组件。
父组件代码:
```text
{{ slotProps.data }}
```
父组件用`v-slot`来接收数据,并渲染到页面上。
### 1.7、v-model
`v-model`可以在组件上使用以实现双向绑定,`vue`内部会帮你传递值和绑定事件,也是达到了父子组件通讯的效果。
从`vue3.4`开始,还可以使用`defineModel`便利宏,其用法如下:
子组件代码:
```text
// Child.vue
Parent:{{ modelValue }}
```
`defineModel`的返回值就是一个`ref`,你可以随意访问和修改它,并且它会和父组件的`v-model`绑定的值保持同步,也就是实现了`双向绑定`。
## 二、兄弟组件
两个兄弟关系组件进行通信,我们一般会借助`第三方媒介`。
### 2.1、mitt
`mitt`相当于我们`vue2`的事件总线`$bus`,只是`vue3`将其废弃,所以我们借助`mitt`实现类似`$bus`的效果。
用法如下:
1. 安装`mitt`
```text
npm install mitt
```
1. 初始化`mitt`
```text
// emitter.js
import mitt from'mitt';
export default mitt();
```
兄弟组件1:
```text
```
兄弟组件2:
```text
```
### 2.2、$parent
我们可以把`状态(即数据)`定义在父组件中,两个兄弟组件可以借助其`共同的父组件`共享同一份数据,间接实现通信。
### 2.3、vuex/pinia
`vuex`是`vue官方`提供的`状态管理工具`,用它可以实现`全局的状态共享`,自然也可以实现兄弟组件的通信了。当然也可以使用`pinia`替代`vuex`。
### 2.4、app.config.globalProperties
`app.config.globalProperties`是一个全局的对象,在应用内所有组件实例都能访问到,当组件属性名和它发生同名冲突时,采取`就近原则`,以组件的为准,这个就相当于`vue2`的`Vue.prototype`。
## 三、跨层级通信
### 3.1、mitt
`mitt`可以实现全局的通信,这个在上面介绍`兄弟组件通信`的时候已经说过,这里不再多说了。
### 3.2、vuex/pinia
`vuex`和`pinia`都是全局的状态管理工具,跨层级通信也不再话下。
### 3.3、provide/inject
`provide/inject`是`vue3`提供的可以跨层级通信的方式。
其用法如下:
1. 在`父组件/根组件`中定义`provide`,提供数据。
```text
// App.vue
```
1. 在`子组件/孙子组件`中使用`inject`,注入数据。
```text
// 后代组件
```
## 四、其它方式
### 4.1、浏览器本地存储`storage`
`html5`提供了一套`storage API`,包括了`localStorage`和`sessionStorage`,它实现`持久化存储、缓存`等功能,自然也可以用来组件间通信了。
```text
// 组件A
// 组件B
```
这里我在组件A使用`sessionStarge`设置了一个`name`值,在组件B里面就能拿到了,只要保证`获取值在设置值之后执行`就行了。
### 4.2、全局`window`对象(不推荐使用)
`window`作为一个全局对象,当然也可以使用它来通信了,不过它既然谁都可以访问到,就存在如下问题:
1. `命令冲突问题`;
2. `难以追踪数据修改,可维护性差`;
3. `挂在window上的数据难以销毁,从而造成内存泄漏`。
所以不推荐使用`window`对象进行通信。
### 4.3、 ES6模块化import/export
我们可以使用ES5的模块化规范`import/export`实现通信。
```text
// a.js
export let a = undefined;
setTimeout(() => {
a = 1;
}, 1000)
// b.js
import { a } from './a.js'
setTimeout(() => {
console.log(a); // 打印1
}, 2000)
```
由于`ES module`采用的是`符号绑定`,所以就算`export`的值是一个`基本数据类型的值`,后续修改了也能访问到。
## 小结
上面介绍了总结了`14种vue3的组件通信方式`,包括:
1. `props`
2. `defineEmits`
3. `$attrs`
4. `$ref + defineExpose`
5. `$parent`
6. `作用域插槽`
7. `v-model`
8. `mitt`
9. `vuex/pinia`
10. `app.config.globalProperties`
11. `provide/inject`
12. 浏览器本地存储`storage`
13. 全局`window`对象
14. ES6模块化`import/export`
希望能对大家有帮助!
propsData:{{ msg }}
```
### 1.2、子传父:`defineEmits`
通过`defineEmits`可以让子组件的值传递到父组件中。
其用法如下:
1. 先在子组件中用`defineEmits([...emitName])`定义一个或多个`emit`,它的返回值是一个`emits`函数,然后可以通过调用`emits`函数向父组件发射时间,并携带参数。
```text
// Child.vue
child
```
1. 在父组件中通过`@符 + 事件名`监听子组件发射出来的事件,并接收其传过来的值。
```text
// Parent.vue
Parent
```
在`vue2`的组件中还可以通过`this.$on`、`this.$emit`来`监听`、`发射`事件,以达到传值的目的,但在`vue3`中`已废弃`这种写法。
### 1.3、`$attrs`
如果需要在子组件中接收的`props`很多,如果在`props`声明比较繁琐,所以vue给我们提供了一个优雅的解决方案,即`$attrs`,`$attrs`指的是父组件传递给子组件的所有属性中,剔除在`props`中定义的那部分之后,剩下的就会放在`$attrs`中。
举个例子:
```text
// Parent.vue
Parent
```
这里父组件给子组件传递了两个属性`msg1`、`msg2`。
```text
// Child.vue
child: {{ $attrs }}
```
这里子组件使用了`defineProps`定义了`msg1`,则页面中`$attrs`的值为`{ msg2: 2 }`。
还可以使用`v-bind`将`$attrs`的所有数据,以属性的方式全部传递到子组件中,我们平常在封装组件的时候,这个东西就能帮助我们实现组件的属性透传,十分好用。
```text
Parent
```
### 1.5、`$parent`
`$parent`代表`当前组件的父组件实例`,如果当前组件是顶层组件,则`$parent`的值为`null`。
我们可以通过`$parent`拿到父组件的实例,自然就可以进行父子组件的交互了。一般也是和`defineExpose`配合使用,和`$ref + defineExpose`用法类似,这里就不多说了。
> 注意:`$children`在vue3中已经废弃,无法使用。
### 1.6、作用域插槽
通过`作用域插槽`可以实现子组件向父组件传递数据。
子组件代码:
```text
model的值: {{ model }}
```
父组件代码:
```text
// Parent.vue
本文来自投稿,不代表本站立场,如若转载,请注明出处:http//www.knowhub.vip/share/2/3187
- 热门的技术博文分享
- 1 . ESP实现Web服务器
- 2 . 从零到一:打造高效的金仓社区 API 集成到 MCP 服务方案
- 3 . 使用C#构建一个同时问多个LLM并总结的小工具
- 4 . .NET 原生驾驭 AI 新基建实战系列Milvus ── 大规模 AI 应用的向量数据库首选
- 5 . 在Avalonia/C#中使用依赖注入过程记录
- 6 . [设计模式/Java] 设计模式之工厂方法模式
- 7 . 5. RabbitMQ 消息队列中 Exchanges(交换机) 的详细说明
- 8 . SQL 中的各种连接 JOIN 的区别总结!
- 9 . JavaScript 中防抖和节流的多种实现方式及应用场景
- 10 . SaltStack 远程命令执行中文乱码问题
- 11 . 推荐10个 DeepSeek 神级提示词,建议搜藏起来使用
- 12 . C#基础:枚举、数组、类型、函数等解析
- 13 . VMware平台的Ubuntu部署完全分布式Hadoop环境
- 14 . C# 多项目打包时如何将项目引用转为包依赖
- 15 . Chrome 135 版本开发者工具(DevTools)更新内容
- 16 . 从零创建npm依赖,只需执行一条命令
- 17 . 关于 Newtonsoft.Json 和 System.Text.Json 混用导致的的序列化不识别的问题
- 18 . 大模型微调实战之训练数据集准备的艺术与科学
- 19 . Windows快速安装MongoDB之Mongo实战
- 20 . 探索 C# 14 新功能:实用特性为编程带来便利