Vue组件间的通信方式究竟有哪些

组件间通信的概念

在介绍方法之前,我们先来了解下什么是组件间通信。

我们都知道,组件是Vue的核心功能之一。每个Vue中的.Vue 文件都可以把它看做一个组件。

通信是指发送者通过某种媒体、某种格式将传递信息传递给收集者来达到某种目的。

从广义上来说,任何信息的交通都是组件间通信 ,即组件(.Vue)通过某种方式来传递信息以达到某个目的。来看个例子,我们在使用UI框架中的table组件,可能会往这个组件中传入一些数据,这就形成了组件间的通信。

通信种类

组件间的通信可以分成四个类型:

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

组件间通信的方案

1.props

props只能从父组件传递给子组件,也就是所谓的单向传递。通过在子组件设置props属性,来定义从父组件那接收的参数。而且父组件可以通过子组件标签来传递值。

Father 复制代码
<Children name="jack" age=18 />  
Children 复制代码
props:{  
    // 字符串形式  
 name:String // 接收的类型参数  
    // 对象形式  
    age:{    
        type:Number, // 接收的类型为数值  
        defaule:18,  // 默认值为18  
       require:true // age属性必须传递  
    }  
} 

2.$emit

$emit是子组件向父组件传递数据的方法。

$emit之所以可以让子组件向父组件传递参数,是因为父组件在子组件中利用v-on来监听函数并接收参数。

子组件通过$emit触发自定义事件,$emit的第二个参数是传递的数值。

Father 复制代码
<Children @add="cartAdd($event)" />  
Children 复制代码
this.$emit('add', good) 

3.ref

ref想必都很熟悉,父组件可以通过设置子组件ref来获取数据。如果在普通的DOM元素上使用,则指向DOM元素;在子组件上使用则指向组件实例,可以通过实例来直接调用组件的方法或访问数据。

Father 复制代码
<Children ref="foo" />  
  
this.$refs.foo  // 获取子组件实例,通过子组件实例我们就能拿到对应的数据  

4.EventBus

EventBus用于兄弟组件之间传值,首先要创建一个中央事件总线,兄弟组件则是通过$emit触发自定义事件,另一个兄弟组件是通过$on来监听自定义事件。

js 复制代码
// 创建一个中央时间总线类  
class Bus {  
  constructor() {  
    this.callbacks = {};   // 存放事件的名字  
  }  
  $on(name, fn) {  
    this.callbacks[name] = this.callbacks[name] || [];  
    this.callbacks[name].push(fn);  
  }  
  $emit(name, args) {  
    if (this.callbacks[name]) {  
      this.callbacks[name].forEach((cb) => cb(args));  
    }  
  }  
}  
  
// main.js  
Vue.prototype.$bus = new Bus() // 将$bus挂载到vue实例的原型上  
// 另一种方式  
Vue.prototype.$bus = new Vue() // Vue已经实现了Bus的功能 
Children1 复制代码
this.$bus.$emit('foo')  
Children2 复制代码
this.$bus.$on('foo', this.handle)  

5.parent或$root

通过共同的祖先$parent$root搭建通信桥连。

Children1 复制代码
this.$parent.on('add',this.add)
Children2 复制代码
this.$parent.emit('add')

6.attrs和$listeners

$attrs$listeners是Vue中的两个属性,$attrs包含父作用域中传递给子组件的所有属性(除了classstyle和被声明为props的属性)。

它是一个对象,包含剩下所有的HTML特性和事件监听器。而且还可以通过v-bind=$attrs传入内部组件。

js 复制代码
// child:并未在props中声明foo  
<p>{{$attrs.foo}}</p>  
  
// parent  
<HelloWorld foo="foo"/>  
js 复制代码
// 给Grandson隔代传值,communication/index.vue  
<Child2 msg="lalala" @some-event="onSomeEvent"></Child2>  
  
// Child2做展开  
<Grandson v-bind="$attrs" v-on="$listeners"></Grandson>  
  
// Grandson使⽤  
<div @click="$emit('some-event', 'msg from grandson')">  
{{msg}}  
</div>  

7.provide和inject

provideinject是Vue中在组件中进行依赖注入的两个选项它们允许祖先组件向子孙组件传递数据或资源。这个方法尤其是在嵌套层级较深时特别适合,如果使用props$emit会难以维护。

现在祖先组件定义provide属性,返回传递的值;再到子孙组件通过inject接受组件传递过来的值。

Father 复制代码
provide(){  
    return {  
        foo:'foo'  
    }  
Children 复制代码
inject:['foo']

8.vuex

vuex是Vue自身的状态管理模式和库。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方法发生变化。

重要概念

  1. State(状态):存储应用层的状态,任何状态更新都应该遵循Vuex的规定流程。
  2. Getter:类似于Vue中的计算属性,可以从State中派生出一些状态;可以接受state作为第一个参数,也可以接受其他getters作为第二个参数。
  3. Mutation:想要更改store状态的唯一方法是提交mutation。每个mutation都带有一个type(事件类型)和handler(回调函数)。

注意:Mutation必须是同步函数。

  1. Action:与Mutation相似但略有不同,Action提交的是Mutation而不是直接改变状态,而且Action可以包含任意的异步操作。Action要通过satore.dispatch来触发。
  2. Module:Vuex允许我们将store切割成模块(Module)。每个模块都拥有自己的state、mutation、action、getter和嵌套子模块------自上而下进行同样方式的分割。

总结

  • 父子关系的组件数据传递选择 props$emit进行传递,也可选择ref
  • 兄弟关系的组件数据传递可选择$bus,其次可以选择$parent进行传递。
  • 祖先与后代组件数据传递可选择attrslisteners或者 ProvideInject
  • 复杂关系的组件数据传递可以通过vuex存放共享的变量。
相关推荐
Enti7c4 分钟前
页面重构过程中如何保证良好的跨浏览器一致性?
前端·其他
海狸鼠11 分钟前
几行代码实现MCP服务端/客户端(接入DeepSeek)
前端·后端
木木黄木木17 分钟前
基于HTML5的拖拽排序功能实现详解
前端·html·html5
Stupid20 分钟前
[学习笔记] 工程化的浅入了解
前端
阿航hang21 分钟前
Reactivity 模块
前端
PineSongCN23 分钟前
nginx 反向代理后SSE连接无效的问题
前端
还是鼠鼠23 分钟前
Node.js 路由 - 初识 Express 中的路由
前端·vscode·前端框架·npm·node.js·express
Moment26 分钟前
岗位急招,算法实习、音乐生成、全栈、flutter 都有,早十晚六 😍😍😍
前端·后端·面试
最新资讯动态28 分钟前
想让鸿蒙应用快得“飞起”,来HarmonyOS开发者官网“最佳实践-性能专区”
前端
我是小趴菜30 分钟前
Vue项目开启代码压缩
前端