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存放共享的变量。
相关推荐
@PHARAOH43 分钟前
WHAT - 前端开发流程 SOP(标准操作流程)参考
前端·领导力
松树戈1 小时前
plus-ui&RuoYi-Vue-Plus 基于pgSql本地运行实践
前端·vue.js·spring boot·ui
new6669992 小时前
css画图形
前端·css
Yvonne爱编码3 小时前
CSS- 1.1 css选择器
前端·css·状态模式·html5·hbuilder
山河故人1633 小时前
uniapp使用npm下载
前端·npm·uni-app
-曾牛3 小时前
基于微信小程序的在线聊天功能实现:WebSocket通信实战
前端·后端·websocket·网络协议·微信小程序·小程序·notepad++
一口一个橘子4 小时前
[ctfshow web入门] web72
前端·web安全·网络安全
Web极客码4 小时前
如何使用WordPress SEO检查器进行实时内容分析
前端·seo·wordpress
Stella25214 小时前
【Vue】CSS3实现关键帧动画
前端·vue.js·css3
junjun.chen06064 小时前
【在qiankun模式下el-dropdown点击,浏览器报Failed to execute ‘getComputedStyle‘ on ‘Window‘: parameter 1 is not o
前端·javascript·前端框架