Vue中的组件通信

F#函数派
• 阅读 1690

前言

vue中的组件通信是必不可少的使用场景,回顾了平时使用vue中碰到的一些业务场景和对应采用的组件通信方式,简单地做了一个归类总结,大致有以下一些通信方式:

props/$emit

定义

最常用的父子组件通信方式,父组件通过props向子组件传值,子组件通过$emit事件向父组件触发事件并传值

实例说明
//父组件
<parent :name="xxx" @updateFromChild="xxx"></parent>

//子组件
props: {
    name: {
        type: String,
        default: ''
    }
}
methods: {
    xxx () {
        this.$emit('updateFromChild', xx)
    }
}

$attrs 和 \$listeners

$attrs:

定义

子组件中获取除了在props中定义之外的父组件中传递的属性值(class 和 style 除外)

实例说明
//父组件
<parent name="小明" age=5 sex="男" home="杭州" class="parent"></parent>

//子组件
<script>
props: {
    name: {
        type: String,
        default: ''
    }
}
mounted () {
    console.log(this.$attrs)
    // {age:5, sex:"男", home:"杭州"}
}
</script>
使用场景

当孙组件中需要用到爷组件中的大量属性,但是父组件却不需要用到很多,只是作为一个中转的传递,巧用$attrs可以节省在父组件中写的props值。

//父组件
<parent name="小明" age=5 sex="男" home="杭州" class="parent"></parent>

//子组件
<template>
  <grand-son :passAttr="$attrs"></grand-son>
</template>

props: {
    name: {
        type: String,
        default: ''
    }
}

$listener:

定义

包含了父作用域中的 (不含 .native 修饰器的) v-on 事件监听器。

实例说明
//父组件
<parent @change="onChange" @hide="OnHide"></parent>

//子组件
<script>
mounted () {
    console.log(this.$listener)
    // {change:f, hide:f}
}
</script>
使用场景

子组件中调用父组件的方法


provide 和 inject

provide:

是一个对象或返回一个对象的函数。该对象包含可注入其子孙的属性

inject:

是一个数组或者对象,包含祖先组件中注入的属性

实例说明:

//父组件:
<script>
provide: {
    name: '小明',
    sayName () {
        console.log('我是' + this.name)
    }
}
mounted() {
    this.name = '小花'
}
</script>


//子组件
<script>
inject:['name', 'sayName'],
mounted () {
    console.log(this.name); //小明
    this.sayName() //我是小明
}
</script>

可以看到在子组件中的 mounted 中打印出了 inject 中传递进来的 name 属性,并成功执行了 sayName 方法。而且 name 属性值还是'小明',并没有变成'小花',并不是响应式的。

注意点

  • provide 和 inject 成对出现使用
  • provide 注入的属性,在组件下的所有子孙组件中都能在 inject 中拿到
  • provide 和 inject 绑定并不是可响应的,这是和props的本质区别

$parent 和 \$children

定义:

已创建的实例的父实例和子实例中,子实例可以用 this.\$parent 访问父实例,子实例被推入父实例的 \$children 数组中,父实例可以用 this.$children 访问子实例。

实例说明

//父组件
mounted(){
console.log(this.$children)
//可以操作子组件的data,或者调用其methods中的方法
}

//子组件
mounted(){
console.log(this.$parent) //可以拿到父组件中的属性和方法
}

注意点

  • \$children和$parent不是响应式的
  • Vue官方有说明节制地使用 \$parent 和 $children - 它们的主要目的是作为访问组件的应急方法。

$refs

定义

一个对象,持有注册过 ref attribute 的所有 DOM 元素和组件实例。通过this.$refs.xxx 可以拿到 xxx 子组件中的data和methods。

实例说明
//父组件
<child ref="child"></child>

mounted(){
this.$refs.child.sayHello() // hello
}

//子组件
methods: {
    sayHello () {
        console.log('hello')
    }
}
注意点
  • this.$refs.xxx 必须在 xxx 组件渲染完成之后才能拿到,并不是所有生命周期中都能取到。
  • 通过 this.$refs.xxx 进行对子组件的属性操作并不是响应式的,因此避免在computed中进行使用。这是一个很好的应急手段,常用于以下两种使用场景

    1. 父组件直接调用子组件中的方法,节省不必要的代码重写
    2. 用来取代JQuery或者JS原生方法对dom元素的获取

vuex

不多说,强大的复杂单页面全局数据通信管理中心,供页面中的每个组件进行全局数据的操作,并响应式到各个组件中。如果不知道自行搜索。这里就简单说两个注意点

  • 注意vuex的使用场景,不要滥用,复杂的页面数据管理,如果只是简单的数据通信用props和$emit即可,不要为了用而用,适合的才是最好的
  • vuex中可以根据情况进行分模块管理,代码的可维护性会得到进一步提升

eventBus

定义

对于非父子组件来说,可以采用一个中间介质来作为一个中央事件总线,完成事件的触发和监听,并进行传值。

实例说明

第一步:创建事件总线:建立一个eventBus.js文件

//仅仅是为了创建一个vue实例
import Vue from 'vue'
export default new Vue()

第二步:在传值的源头组件中引进事件总线,进行事件的触发和传值

<template>
 <div class = "source">
   <button @click="emitEvent">
 </div>
</template>

<script>
import eventBus from './eventBus.js'
export default {
  methods: {
      emitEvent: funciton () {
        eventBus.$emit('sendVal',param)
      }
  }
}
</script>

第三步:在传值的目标组件中引进事件总线,进行事件的监听和传值的接收

<template>
 
</template>

<script>
import eventBus from './eventBus.js'
export default {
  data: function () {
      return {
          requireVal: ''
      }
  }
  mounted: function () {
    var that = this
    eventBus.$on('sendVal',function(val){
        that.requireVal = val
    }) 
  }
}
</script>

总结如下:

1.创建一个事件总线,例如demo中的eventBus,用它作为通信桥梁

2.在需要传值的组件中用bus.$emit触发一个自定义事件,并传递参数

3.在需要接收数据的组件中用bus.$on监听自定义事件,并在回调函数中处理传递过来的参数

注意点
  • eventBus 特别适合非跨多个层级组件之间的通信,解决了通过层层props传递的繁琐,也避免了使用vuex的相对臃肿。
  • 缺陷在于如果不加说明和规范管理,容易找不到事件的触发者和监听者。因此建议放在单独的js文件中创建好eventBus的vue实例,并在该文件中注释好事件的触发组件和监听组件。
点赞
收藏
评论区
推荐文章
晴空闲云 晴空闲云
4年前
vue3中基于script setup语法糖的$refs使用
在用vue3开发项目的时候,需要调用子组件的方法,于是想着用$refs来实现,但是我是使用scriptsetup语法糖,原先vue2的语法已经不适用了。于是一番折腾和查阅资料,终于搞定。vue2语法vue2语法在组件上设置ref属性后,在代码里可以通过this.$refs.ref值访问到对应的子组件。一个设置ref值的组件:html在js代码中可以通
Oracle 分组与拼接字符串同时使用
SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(
Alex799 Alex799
4年前
vue最新面试题
最近在面试,总结几个重点的面试题:一、vue父子组件之间的传值:简单来说,子组件通过props方法接受父组件传来的值,子组件通过$emit方法来向父组件发送数据。(具体案例可以看我之前写的博客)。二、vue生命周期函数:beforeCreatecreatedbeforeMountmountedbeforeUpdateupdatedbeforeDestr
Chase620 Chase620
4年前
vue的8种通信方式
1.props/emit1.父组件向子组件传值下面通过一个例子说明父组件如何向子组件传递数据:在子组件article.vue中如何获取父组件section.vue中的数据articles:\'红楼梦','西游记','三国演义'\//section父组件<template<divclass"section"
Souleigh ✨ Souleigh ✨
5年前
React 组件间通信的10种方法
组件间通信方式总结父组件子组件:1.Props2.InstanceMethods子组件父组件:1.CallbackFunctions2.EventBubbling兄弟组件之间:1.ParentComponent不太相关的组件之间:1.Context2.Portals3.Global
科林-Colin 科林-Colin
5年前
Vue 组件通信方式及其应用场景总结
前言相信实际项目中用过vue的同学,一定对vue中父子组件之间的通信并不陌生,vue中采用良好的数据通讯方式,避免组件通信带来的困扰。今天笔者和大家一起分享vue父子组件之间的通信方式,优缺点,及其实际工作中的应用场景首先我们带着这些问题去思考1vue中到底有多少种父子组件通信方式?2vue中那种父子组件最佳通信方式是什么?3
爱丽丝13 爱丽丝13
5年前
React 组件通信之发布订阅模式
React通信react的数据流是单向的,react通信有以下几种方式:父向子通信:传入props子向父通信:父组件向子组件传一个函数,然后通过这个函数的回调,拿到子组件传过来的值父向孙通信:利用context传值。React.createContext()兄弟间通信:​1、找一个相同的父组件,既可以用pr
Dax Dax
4年前
Vue父子组件
几种常见的通信方式:1、prop属性父组件通过绑定属性的方式,给子组件传值,同时子组件通过设置props来接收letChildVue.extend(template:'content',props:content:type:String,default:()r
马丁路德 马丁路德
4年前
vue3 - 组件通信
vue3组件通信和vue2的通信方式基本一致,只是存在写法上的差异props/emitsetup函数接收两个参数,props和context(上下文,其中有一个emit)用法展示//父组件<template<ibutton:type'type'@onClick
可莉 可莉
4年前
04. react 初次见面
    组件从概念上看就像是函数,它可以接收任意的输入值(称之为“props”),并返回一个需要在页面上展示的React元素。1、组件定义的两种方式1.1函数定义组件  定义一个组件最简单的方式是使用JavaScript函数:functionWelcome(props){return<
Stella981 Stella981
4年前
34条我能告诉你的Vue之实操篇
这是我学习整理的关于Vue.js系列文章的第一篇,另外还有两篇分别是关于优化和原理的。希望读完这3篇文章,你能对Vue有个更深入的认识。7种组件通信方式随你选组件通信是Vue的核心知识,掌握这几个知识点,面试开发一点问题都没有。props/@on$emit用于实现父子组件间通信。通过