Vue中的组件通讯

前言

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

props/$emit

定义

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

实例说明
//父组件
<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值。dom

//父组件
<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 事件监听器。ide

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

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

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


provide 和 inject

provide:

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

inject:

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

实例说明:

//父组件:
<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 属性值仍是'小明',并无变成'小花',并非响应式的。code

注意点

  • 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实例,并在该文件中注释好事件的触发组件和监听组件。
相关文章
相关标签/搜索