vue2.x组件通信有哪些方式,vue组件间通信六种方式(完整版)

  vue2.x组件通信有哪些方式,vue组件间通信六种方式(完整版)

  vue组件的通讯方式,这是面试中出现频率非常高的问题。其实vue组件除了props和$emit还有很多通信方式。本文将总结Vue组件的通信方式,有兴趣的可以借鉴。

  

目录

   1.props/$emit轮廓代码示例2.v形槽轮廓代码示例3。$ refs/$ parent/$ children/$ root配置文件代码示例4。$attrs/$listener profile代码示例5.provide/代码示例注入简介6。6.eventBus介绍原理分析7 .代码示例。7.vuex的代码示例总结了vue组件的通信方式,是面试中出现频率非常高的问题。刚开始找实习的时候经常遇到这个问题。那时候我只知道回道具和$emit。后来随着学习的深入,才发现Vue组件的通信方式竟然这么多!

  今天总结一下vue组件的通讯方式,如有遗漏请留言。

  

1. props/$emit

  

简介

  道具和$emit相信大家都很熟悉。这是我们最常用的vue沟通方式。

  Props:props可以是一个数组,也可以是一个对象,用来从父组件接收v-bind传递的数据。当props为数组时,直接接收父组件传递的属性;当props为对象时,可以通过类型、默认值、是否必选、验证器等配置来设置属性的类型、默认值、是否必选以及验证规则。

  $emit:父子组件通信时,我们通常用$emit触发父组件v-on绑定子组件上相应的事件进行监听。

  

代码实例

  下面的代码用来实现props和$emit之间的父子组件通信。在这个例子中,我们都实现了以下通信:

  将值从父组件传递到子组件:父组件通过:messageFromParent= message 将父组件的消息值传递到子组件。当父组件的输入标签被输入时,子组件的p标签中的内容会相应地改变。

  从子组件向父组件传递值:父组件通过@on-receive=receive 将接收事件的监视绑定到子组件上。当子组件的input标签被输入时,receive回调函数会被触发,子组件消息的值会通过这个赋给父组件messageFromChild。$ emit (on-receive ,this.message),更改父组件P标记的内容。

  请看代码:

  //子组件代码

  模板

  div class=child

  h4这是子组件/h4

  input type= text v-model= message @ keyup= send /

  p收到来自父组件的消息:{{MessageFromparet}}/p

  /div

  /模板

  脚本

  导出默认值{

  姓名:孩子,

  Props: [MessageFromparet],//通过Props接收来自父组件的消息

  data() {

  返回{

  消息: ,

  }

  },

  方法:{

  send() {

  这个。$emit (on-receive ,this.message)//通过$emit触发on-receive事件,调用父组件中的receive回调,以this . message为参数。

  },

  },

  }

  /脚本

  //父组件代码

  模板

  div class=parent

  h3这是父组件/h3

  输入类型=text v-model=message /

  p收到来自子组件的消息:{{ messageFromChild }}/p

  child:message from parent= message @ on-receive= receive /

  /div

  /模板

  脚本

  从导入子级。/孩子

  导出默认值{

  姓名:家长,

  data() {

  返回{

  消息: ,//传递给子组件的消息

  messageFromChild: ,

  }

  },

  组件:{

  孩子,

  },

  方法:{

  Receive(msg) {//接受子组件的信息,并将其分配给messageFromChild

  this.messageFromChild=msg

  },

  },

  }

  /脚本

  效果预览

  

2. v-slot

  

简介

  V-slot是2.6版本中新增的统一实现插槽和命名插槽的api,用于替代slot(2.6.0过时)、slot-scope(2.6.0过时)、scope(2.5.0过时)等API。

  模板标签中使用V-slot来提供命名插槽或需要接收prop的插槽。如果未指定v-slot,则默认值为default。

  

代码实例

  让我们来看看v-slot的代码示例,我们在其中实现了:

  从父到子传递值:父组件通过模板v-slot:child { { message } }/template将父组件的消息值传递给子组件,子组件通过slot name=child/slot接收相应的内容,从而实现父到子的值传递。

  //子组件代码

  模板

  div class=child

  h4这是子组件/h4

  p收到来自父组件的消息:

  slot name=child/slot!-显示父组件通过插槽传递的{{message}}

  /p

  /div

  /模板

  模板

  div class=parent

  h3这是父组件/h3

  输入类型=text v-model=message /

  儿童

  模板v形槽:子

  {{ message }}!-插槽会显示什么-

  /模板

  /孩子

  /div

  /模板

  脚本

  从导入子级。/孩子

  导出默认值{

  姓名:家长,

  data() {

  返回{

  消息: ,

  }

  },

  组件:{

  孩子,

  },

  }

  /脚本

  效果预览

  

3. $refs/ $parent/ $children/$root

  

简介

  我们还可以通过$refs/$parent/$children/$root获取Vue组件的实例,获取实例上绑定的属性和方法,从而实现组件之间的通信。

  $refs:我们通常将$refs绑定到DOM元素来获取DOM元素的属性。在实现组件通信时,我们还可以将$refs绑定到子组件,以获得子组件实例。

  $parent:我们可以通过这个直接得到当前组件的父组件实例(如果有的话)。Vue中的$parent。

  $children:同理,我们也可以通过这个直接得到当前组件的子组件实例的数组。Vue的儿童。然而,应该注意的是,元素下标在这个。$children数组不一定会影响父组件引用的子组件的顺序,例如,异步加载的子组件可能会影响它们在子数组中的顺序。所以需要根据一定的条件找到对应的子组件,比如子组件的名称。

  $root:获取当前组件树的根Vue实例。如果当前实例没有父实例,则该实例将是自己的实例。通过$root,我们可以实现组件之间的跨层通信。

  

代码实例

  让我们来看一个使用$ parent和$ children的例子。(由于这些API的使用方式相似,所以这里不展开$ refs和$ root的使用。它在本例中实现:

  将值传递给父组件和子组件:子组件通过$ parent.message获取父组件中消息的值。

  将值从子组件传递到父组件:父组件通过$children获得子组件实例的数组,然后通过遍历数组,通过实例的名称获得相应的Child1子组件实例,将其赋给child1,然后通过child1.message获得Child1子组件的消息

  代码如下:

  //子组件

  模板

  div class=child

  h4这是子组件/h4

  输入类型=text v-model=message /

  收到来自父组件的消息:{{ $parent.message }}/p!-显示父组件实例的消息-

  /div

  /模板

  脚本

  导出默认值{

  名称:“孩子1”,

  data() {

  返回{

  Message: ,//父组件可以通过这个得到子组件实例的消息。$儿童。

  }

  },

  }

  /脚本

  //父组件

  模板

  div class=parent

  h3这是父组件/h3

  输入类型=text v-model=message /

  p收到来自子组件的消息:{{ child1.message }}/p!-消息-显示子组件的实例-

  孩子/

  /div

  /模板

  脚本

  从导入子级。/孩子

  导出默认值{

  姓名:家长,

  data() {

  返回{

  消息: ,

  孩子1: {},

  }

  },

  组件:{

  孩子,

  },

  已安装(){

  this.child1=this。$children.find((child)={

  return child . options.name=== child 1 //通过options . name获取对应名称的子实例

  })

  },

  }

  /脚本

  效果预览

  

4. $attrs/$listener

  

简介

  $ attrs和$ listeners是Vue2.4中新增加的属性,主要用于用户开发高级组件。

  $attrs:用于接收父作用域中不被识别为prop的attribute属性,可以通过v-bind=$attrs 传入内部组件——。这在创建高级组件时非常有用。

  想象一下,当你创建一个组件的时候,你要接收几十个参数,比如param1,param2,param3 ……等等。如果你通过道具,那么你需要通过道具声明很多:[param1 , param2 , param3 ,…]等。如果这些道具中的一部分还需要传递给更深层次的子组件,那就比较麻烦了。

  使用$attrs,您不需要任何声明。可以通过$attrs.param1,$ attrs.param2直接使用.而且把上面的例子传递给深子组件也很方便。

  $listeners:包含父作用域中的v-on事件侦听器。可以通过v-on=$listeners 传入内部组件3354,这对于创建更高级别的组件非常有用。在这里,传递的方法与$attrs非常相似。

  

代码实例

  在这个例子中,有三个组件:A、B和C,它们的关系是:[A [B [C]]],A是B and B的父组件是C的父组件.即一级组件A、二级组件B和三级组件C.我们已经实现了:

  向父子传递值:一级组件A通过:messageFromA=message 向二级组件B传递消息属性,二级组件B通过$ attrs.message从A获取一级组件A的消息。

  :messageFromA=message

  v-bind=$attrs

  $attrs.messageFromA

  将值传递给子组件和父组件:1级组件A通过@keyup=receive 绑定子组件和孙组件上的keyup事件的监视,2级组件B通过v-on=$listeners 将keyup事件绑定到其输入标记。当二级组件B的输入框被输入时,一级组件A的receive回调将被触发,二级组件B的输入框中的值将被赋给一级组件A的messageFromComp,从而实现值从子到父的传递。

  @keyup=receive

  CompC v-on=$listeners /

  v-on=$listeners

  代码如下:

  //三级组件C

  模板

  div class=compc

  h5这是C组件/h5

  input name= compC type= text v-model= message v-on= $ listeners /!-将组件A keyup的监视回调绑定到输入-

  p收到来自组件A的消息:{{ $attrs.messageFromA }}/p

  /div

  /模板

  脚本

  导出默认值{

  名称: Compc ,

  data() {

  返回{

  消息: ,

  }

  },

  }

  /脚本

  //二级组件B

  模板

  div class=compb

  h4这是B组件/h4

  input name= compB type= text v-model= message v-on= $ listeners /!-将组件A keyup的监视回调绑定到输入-

  p收到来自组件A的消息:{{ $attrs.messageFromA }}/p

  CompC v-bind= $ attrs v-on= $ listeners /!-继续将组件a keyup的监听回调传递给组件c,继续将组件a传递的attrs传递给组件c-

  /div

  /模板

  脚本

  从导入CompC。/compC

  导出默认值{

  名称: CompB ,

  组件:{

  CompC,

  },

  data() {

  返回{

  消息: ,

  }

  },

  }

  /脚本

  //一个组件

  模板

  div class=compa

  h3这是组件/h3

  输入类型=text v-model=message /

  p收到来自{{ comp }}: {{ messageFromComp }}/p的消息

  CompB:message froma= message @ keyup= receive /!-侦听后代组件的keyup事件,并将消息传递给后代组件-

  /div

  /模板

  脚本

  从导入CompB。/compB

  导出默认值{

  名称:公司,

  data() {

  返回{

  消息: ,

  messageFromComp: ,

  组件: ,

  }

  },

  组件:{

  CompB,

  },

  方法:{

  Receive(e) {//监听子组件keyup事件的回调,将keyup所在的输入输入框的值赋给messageFromComp。

  this.comp=e.target.name

  this . messagefromcomp=e . target . value

  },

  },

  }

  /脚本

  效果预览

  

5. provide/inject

  

简介

  provide/inject选项需要一起使用,以允许祖先组件将依赖项注入到它的所有后代中,无论组件层次结构有多深,并且只要建立了上下游关系,它就会一直生效。如果是熟悉React的同学,会马上想到Context api,两者非常相似。

  Provide:是一个对象,或者是一个返回对象的函数。此对象包含可以注入其子代的属性,即要传递给子代的属性和属性值。

  Injcet:字符串数组或对象。当它是一个字符串数组时,它的使用方式与props非常相似,只是接收到的属性从data更改为provide中的属性。当它是一个物体时,它也类似于道具。您可以通过配置属性(如default和from)来设置默认值,并在子组件中使用新的命名属性。

  

代码实例

  本例中有三个组件,一级组件A,二级组件B,三级组件C: [A [B [C]]。a是B and B的父组件,c是它的父组件。该示例实现:

  向父子传递值:一级组件A通过provide将消息注入子代和孙代,二级组件B通过inject接收一级组件A的消息:[messageFromA],通过messageFromA.content从一级组件A获取消息的内容属性值

  跨级值传递:一级组件A通过provide将消息注入其后代,三级组件C通过inject接收一级组件A中的消息:[messageFromA],通过messageFromA.content获取一级组件A中消息的内容属性值,实现跨级值传递。

  代码如下:

  //一级组件A

  模板

  div class=compa

  h3这是组件/h3

  输入类型= text v-model= message . content /

  CompB /

  /div

  /模板

  脚本

  从导入CompB。/compB

  导出默认值{

  名称:公司,

  提供(){

  返回{

  MessageFromA: this.message,//通过provide将消息传递给后代组件。

  }

  },

  data() {

  返回{

  消息:{

  内容: ,

  },

  }

  },

  组件:{

  CompB,

  },

  }

  /脚本

  //二级组件B

  模板

  div class=compb

  h4这是B组件/h4

  收到的来自组件a的消息:{ {来自a. content的消息的消息}}/p

  CompC /

  /div

  /模板

  脚本

  从导入CompC。/compC

  导出默认值{

  名称: CompB ,

  Inject: [messageFromA],//接受提供者在直通注入中传递的消息

  组件:{

  CompC,

  },

  }

  /脚本

  //三级组件C

  模板

  div class=compc

  h5这是C组件/h5

  收到的来自组件a的消息:{ {来自a. content的消息的消息}}/p

  /div

  /模板

  脚本

  导出默认值{

  名称: Compc ,

  Inject: [messageFromA],//接受提供者在直通注入中传递的消息

  }

  /脚本

  注意:

  有些同学可能想问我,为什么上面的一级组件A中的消息使用对象类型而不是字符串类型,因为vue provide和inject之间的绑定是没有响应的。如果消息是字符串类型,通过一级组件a中的输入输入框改变消息值后不能赋给messageFromA,如果是对象类型,对象属性值改变后messageFromA中的属性值仍然可以改变,后代组件inject接收到的对象属性值也可以相应改变。

  子代提供与祖先具有相同的属性,这将在后代中覆盖祖先的提供值。例如,如果2级组件B也通过provide将messageFromA值注入3级组件C,则3级组件C中的messageFromA将首先接收2级组件B注入的值,而不是1级组件A。

  效果预览

  

6. eventBus

  

简介

  EventBus也叫事件总线,注册一个新的Vue实例,通过调用这个实例的$ emit和$ on来监控和触发这个实例的事件,通过传入参数来实现组件的全局通信。它是一个没有DOM的组件,有些只是实例化方法,所以很轻。

  我们可以通过以下方式在全球Vue实例上注册:

  //main.js

  Vue.prototype.$Bus=new Vue()

  但是当项目太大的时候,我们最好把事件总线抽象成一个文件,导入到每个需要使用的组件文件中。这样,就不会污染全局命名空间:

  //bus.js,使用时通过导入引入。

  从“vue”导入Vue

  export const Bus=new Vue()

  

原理分析

  事实上,eventBus的原理相当简单,即使用订阅-发布模式并实现$ emit和$ on:

  //eventBus原理

  导出默认类别总线{

  构造函数(){

  this.callbacks={}

  }

  $on(事件,fn) {

  this . callbacks[event]=this . callbacks[event] []

  this . callbacks[事件]。推动(fn)

  }

  $emit(event,args) {

  这个。回调[事件]。forEach((fn)={

  fn(参数)

  })

  }

  }

  //在主页。射流研究…中引入以下

  //Vue.prototype.$bus=new Bus()

  

代码实例

  在这个实例中,共包含了四个组件:[ A [ B [ C、D ] ],1级组件答,2级组件b,3级组件C和3级组件d。我们通过使用事件总线实现了:

  全局通信:即包括了父子组件相互通信、兄弟组件相互通信、跨级组件相互通信。4个组件的操作逻辑相同,都是在投入输入框时,通过这个。$巴士emit(sendMessage ,obj)触发发送消息事件回调,将发报机和消息封装成对象作为参数传入;同时通过这个。$巴士在( sendMessage ,obj)上监听其他组件的发送消息事件,实例当前组件示例发报机和消息的值。这样任一组件投入输入框值改变时,其他组件都能接收到相应的信息,实现全局通信。

  代码如下:

  //main.js

  Vue.prototype.$bus=new Vue()

  //1级组件A

  模板

  div class=containerA

  氘这是CompA/h2

  input type= text v-model= message @ keyup= sendMessage /

  p v-show=messageFromBus sender!==$options.name

  收到{{发件人}}的消息:{{ messageFromBus }}

  /p

  CompB /

  /div

  /模板

  脚本

  从导入CompB ./compB

  导出默认值{

  名称:公司,

  组件:{

  CompB,

  },

  data() {

  返回{

  消息: ,

  messageFromBus: ,

  发件人: ,

  }

  },

  已安装(){

  这个。$巴士on(sendMessage ,(obj)={ //通过事件总线监听发送消息事件

  const { sender,message }=obj

  this.sender=发送者

  this.messageFromBus=message

  })

  },

  方法:{

  sendMessage() {

  这个。$巴士发出( sendMessage ,{ //通过事件总线触发发送消息事件

  发件人:这个. options.name,

  消息:this.message,

  })

  },

  },

  }

  /脚本

  //2级组件B

  模板

  div class=集装箱船

  h3这是CompB/h3

  input type= text v-model= message @ keyup= sendMessage /

  p v-show=messageFromBus sender!==$options.name

  收到{{发件人}}的消息:{{ messageFromBus }}

  /p

  CompC /

  CompD /

  /div

  /模板

  脚本

  从导入CompC ./compC

  从导入CompD ./compD

  导出默认值{

  名称: CompB ,

  组件:{

  CompC,

  CompD,

  },

  data() {

  返回{

  消息: ,

  messageFromBus: ,

  发件人: ,

  }

  },

  已安装(){

  这个。$巴士on(sendMessage ,(obj)={ //通过事件总线监听发送消息事件

  const { sender,message }=obj

  this.sender=发送者

  this.messageFromBus=message

  })

  },

  方法:{

  sendMessage() {

  这个。$巴士发出( sendMessage ,{ //通过事件总线触发发送消息事件

  发件人:这个. options.name,

  消息:this.message,

  })

  },

  },

  }

  /脚本

  //3级组件C

  模板

  div class=containerC

  p这是CompC/p

  input type= text v-model= message @ keyup= sendMessage /

  p v-show=messageFromBus sender!==$options.name

  收到{{发件人}}的消息:{{ messageFromBus }}

  /p

  /div

  /模板

  脚本

  导出默认值{

  名称: CompC ,

  data() {

  返回{

  消息: ,

  messageFromBus: ,

  发件人: ,

  }

  },

  已安装(){

  这个。$巴士on(sendMessage ,(obj)={ //通过事件总线监听发送消息事件

  const { sender,message }=obj

  this.sender=发送者

  this.messageFromBus=message

  })

  },

  方法:{

  sendMessage() {

  这个。$巴士发出( sendMessage ,{ //通过事件总线触发发送消息事件

  发件人:这个. options.name,

  消息:this.message,

  })

  },

  },

  }

  /脚本

  //3级组件D

  模板

  div class=containerD

  p这是CompD/p

  input type= text v-model= message @ keyup= sendMessage /

  p v-show=messageFromBus sender!==$options.name

  收到了{{ sender }}: {{ messageFromBus }}的邮件

  /p

  /div

  /模板

  脚本

  导出默认值{

  名称: CompD ,

  data() {

  返回{

  消息: ,

  messageFromBus: ,

  发件人: ,

  }

  },

  已安装(){

  这个。$巴士。$ on (sendMessage ,(obj)={//通过eventBus侦听sendMessage事件

  const { sender,message }=obj

  this.sender=发送者

  this.messageFromBus=message

  })

  },

  方法:{

  sendMessage() {

  这个。$巴士。$ emit (sendMessage ,{//通过eventBus触发sendMessage事件

  发件人:这个。$options.name,

  消息:this.message,

  })

  },

  },

  }

  /脚本

  效果预览

  图片太大,截图处理

  

7. Vuex

  当项目庞大,多人维护同一个项目时,如果使用事件总线进行全局通信,很容易使全局变量的变化变得不可预测。于是就有了Vuex的诞生。

  Vuex是专门为Vue.js应用开发的状态管理模式。它采用集中存储来管理应用程序所有组件的状态,并确保状态以可预测的方式随相应的规则变化。

  关于Vuex的内容,请参考Vuex的官方文档[1],这里就不尝试班门弄斧了,只看代码。

  

代码实例

  Vuex的实例和事件总线leisi也包含四个组件:[A [B [C,D]]]一级组件A、二级组件B、三级组件C和三级组件D .我们在这个例子中实现了:

  全局通信:代码内容类似于eventBus,但使用起来比eventBus方便得多。每个组件通过watch监控输入输入框的变化,通过vuex的提交触发突变,从而改变stroe的值。然后各个组件通过计算动态获取存储中的数据,从而实现全局通信。

  //store.js

  从“vue”导入Vue

  从“vuex”导入Vuex

  Vue.use(Vuex)

  导出默认的新Vuex。商店({

  状态:{

  消息:{

  发件人: ,

  内容: ,

  },

  },

  突变:{

  sendMessage(state,obj) {

  state.message={

  发件人:obj.sender,

  内容:obj.content,

  }

  },

  },

  })

  //组件a

  模板

  div class=containerA

  h2这是CompA/h2

  输入类型=text v-model=message /

  p v-show= message from store sender!==$options.name

  收到来自{ { sender } }:{ { messageFromStore } }的消息

  /p

  CompB /

  /div

  /模板

  脚本

  从导入CompB。/compB

  导出默认值{

  名称:公司,

  组件:{

  CompB,

  },

  data() {

  返回{

  消息: ,

  }

  },

  计算值:{

  messageFromStore() {

  归还这个。$store.state.message.content

  },

  发件人(){

  归还这个。$store.state.message.sender

  },

  },

  观察:{

  消息(新值){

  这个。$store.commit(sendMessage ,{

  发件人:这个。$options.name,

  内容:newValue,

  })

  },

  },

  }

  /脚本

  与eventBus中一样,除了引入子组件之外,组件B、C和D中的代码是相同的,因此不再赘述。

  效果预览

  

总结

  7中Vue组件的通信方式如上所述,它们可以进行的通信类型如下图所示:

  Props/$emit:可以实现父子组件的双向通信,一般是我们日常父子组件通信中最常用的选择。

  V-slot:可以实现父子组件之间的单向通信(从父组件向子组件传递值)。实现可复用组件时,将DOM节点、html等内容转移到组件中,对一些组件库的表值进行二次处理等。v槽可以优先。

  $ refs/$ parent/$ children/$ r oot:可以实现父子组件之间的双向通信,其中$ r oot可以实现从根组件实例到其后代的单向值传递。当父组件不传递值或通过v-on绑定监听时,父子如果想获取对方的属性或方法,可以考虑使用这些API。

  $ attrs/$ listeners:它可以实现跨级双向通信,它允许您简单地获取传入的属性和绑定监控,并且可以方便地传递给下属子组件。这在构建高级组件时非常有用。

  提供/注入:可以实现跨级单向通信,轻注入依赖到子代和孙代组件中。当实现高级组件和创建组件库时,这是您的最佳选择。

  EventBus:可以实现全局通信,在项目规模不大的情况下,可以用来实现全局事件监控。但是,应该谨慎使用eventBus,以避免全局污染和内存泄漏。

  Vue:可以实现全球沟通,这是VUE项目全球状态管理的最佳实践。当项目很大,你想集中管理全局组件的状态时,安装Vuex是对的!

  也就是说,彻底理解了Vue组件的七种通信模式的细节。更多关于Vue组件通信方式的信息,请关注我们的其他相关文章!

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: