概述

常见使用场景可以分为三类:

  • 父子通信:
    • 父向子传递数据是通过 props
    • 子向父是通过 events( $emit )
    • 通过父链 / 子链也可以通信( $parent / $children )
    • ref 也可以访问组件实例;provide / inject API。
  • 兄弟通信:Bus;Vuex;
  • 跨级通信:Bus;Vuex;provide / inject API、 a t t r s /attrs/attrs/listeners

props/$emit

父组件中的数据在子组件中不能直接使用,要想在子组件中使用,步骤:
1、 父组件中调用子组件时绑定动态属性
2、 子组件中通过props接收父组件中传递过来的数据
3、 在子组件中使用

示例:父组件向子组件传递数据

  • 子组件
<template><div><h1>子组件</h1><h3>插值表达式获取到:{{msg1}}</h3><h3>插值表达式获取到:{{msg2}}</h3><h3>插值表达式获取到:{{msg3}}</h3></div></template><script>export default {name: 'Child',props: ['msg1', 'msg2', 'msg3']}</script>
  • 父组件:
<template><div><h1>父组件</h1><h-child v-bind:msg1="'来自父组件的数据'"动态绑定:msg2="'data from parent'" 动态绑定的简写形式msg3="'data from parent'" 绑定字符串></h-child></div></template><script>// 引入子组件import HChild from './Child'export default {name: 'Parent',components: {HChild}}</script>

结果:

在子组件中使用props除了可以获取父组件的值之外,还可以验证父组件传递到子组件的数据的合法性,还可以获取父组件本身或者调用父组件中的方法。
示例:父组件向子组件传递数据

  • 父组件
<template><div><h1>父组件</h1><h-child v-bind:msg="'来自父组件的数据'"绑定数据 :pfun="fun"绑定方法 :pComp=this绑定对象></h-child></div></template><script>// 引入子组件import HChild from './Child'export default {name: 'Parent',components: {HChild},methods: {fun () {console.log('parent fun')}}}</script>
  • 子组件
<template><div><h1>子组件</h1><h3>插值表达式获取到:{{msg}}</h3><button @click="pfun">调用父组件的方法</button><br><button @click="cfun">获取父组件</button></div></template><script>export default {name: 'Child',props: {msg: {type: String,default: ''},pfun: {type: Function},pComp: {type: Object}},methods: {cfun () {console.log(this.pComp)this.pComp.fun()}}}</script>
  • 结果

示例:子组件向父组件传递数据
子组件向父组件传值一般通过事件触发实现。

  • 子组件
<template><div><h1>子组件</h1><button @click="passMsg">子组件向父组件传值</button></div></template><script>export default {name: 'Child',methods: {passMsg () {this.$emit('showMsgEvent', '子组件向父组件传递的值')}}}</script>
  • 父组件
<template><div><h1>父组件</h1><h3>插值表达式获取到:{{msg}}</h3><h-child@showMsgEvent="showMsg"></h-child></div></template><script>// 引入子组件import HChild from './Child'export default {name: 'Parent',data () {return {msg: ''}},components: {HChild},methods: {showMsg (val) {this.msg = val}}}</script>

结果:

单击按钮后

$parent/children

parents是当前组件树的根Vue实例。如果当前实例没有父实例,此实例将会是其自己。既然可以获取到组件的实例,那么就可以调用组件的属性或是方法进行操作。换句话说即parents让我们可以在子组件中访问到父组件的data和方法。具体语法为:this.parents是当前组件树的根 Vue 实例。如果当前实例没有父实例,此实例将会是其自己。 既然可以获取到组件的实例,那么就可以调用组件的属性或是方法进行操作。换句话说即parents让我们可以在子组件中访问到父组件的data和方法。具体语法为: this. parentsVueparents访datathis.parent.数据
this.$parent.方法

示例:父组件向子组件传值:子组件主动获取父组件的数据和方法
  • 父组件:
<template><div><h1>父组件</h1><h-child></h-child></div></template><script>// 引入子组件import HChild from './Child'export default {name: 'Parent',components: {HChild},data () {return {msg: 'data from parent'}},methods: {fun () {console.log('parent fun')}}}</script>
  • 子组件:
<template><div><h1>子组件</h1><button @click="showParent">调用父组件的数据和方法</button></div></template><script>export default {name: 'Child',methods: {showParent () {// 获取到所有的子组件console.log(this.$parent)// 获取指定子组件中的指定数据console.log(this.$parent.msg)// 调用子组件的方法this.$parent.fun()}}}</script>

注意:子组件获取父组件中的数据的方法的代码不能直接写在钩子函数mounted中。
结果:

示例:子组件向父组件传值

  • 子组件:
<template><div><h1>子组件</h1></div></template><script>export default {name: 'Child',data () {return {msg: 'msg from child'}},methods: {fun () {console.log('child fun')}}}</script>
  • 父组件:
<template><div><h1>父组件</h1><h-child></h-child></div></template><script>// 引入子组件import HChild from './Child'export default {name: 'Parent',components: {HChild},mounted () {// 获取到所有的子组件,结果是一个数组console.log(this.$children)// 获取指定子组件中的指定数据console.log(this.$children[0].msg)// 调用子组件的方法this.$children[0].fun()}}</script>

注意:

  • $children并不保证顺序,也不是响应式的。使用 $children 来进行数据绑定时,可以考虑使用一个数组配合 v-for 来生成子组件,并且使用 Array 作为真正的来源
  • $children 是一个数组,是直接儿子的集合,儿子里面有个 _uid 属性,可以知道它是第几个元素,_uid是元素的唯一标识符,根据这个属性,我们可以进行其他的操作
    结果

$ref:父组件主动获取子组件的数据和方法

$refs 让我们可以在父组件中进行操作子组件的数据以及方法,使用步骤:

  1. 在父组件中调用子组件时定义一个ref
  2. 在父组件中通过this.$refs..属性/方法

示例:子组件向父组件传值:

  • 子组件:
<template><div><h1>子组件</h1></div></template><script>export default {name: 'Child',data () {return {msg: 'msg from child'}},methods: {fun () {console.log('child fun')}}}</script>
  • 父组件:
<template><div><h1>父组件</h1><h-child ref="children"></h-child></div></template><script>// 引入子组件import HChild from './Child'export default {name: 'Parent',data () {return {msg: 'data from parent'}},components: {HChild},mounted () {// 获取到所有的子组件,结果是一个对象console.log(this.$refs.children)// 获取指定子组件中的指定数据console.log(this.$refs.children.msg)// 调用子组件的方法this.$refs.children.fun()}}</script>

结果

兄弟组件之间传值

原理事件广播方式,步骤:
1、 新建一个js文件,然后引入vue并实例化,最后暴露这个实例
2、 在广播和接收广播的组件中都引入上步中定义的实例
3、 通过emit()广播数据4、通过emit()广播数据 4、 通过 emit()广4on()接收数据

示例:

  • App.vue
<template><div id="app"><v-home></v-home><v-news></v-news></div></template><script>import Home from './views/Home';import News from './views/News';export default {name: 'app',components:{'v-home':Home,'v-news':News}}</script>
  • 在src/utils目录中创建bus.js文件,代码如下:
import Vue from 'vue';//1、引入一个空的Vue实例export default new Vue(); //2、实例化Vue实例并暴露出去
  • Home.vue
<template><div><h2> Home首页 </h2><br><button @click="broadcast2News">给News广播数据</button></div></template><script>import bus from '../utils/bus'export default {methods: {broadcast2News(){//广播数据bus.$emit('data2news', '来自Home的数据');}}}</script>
  • News.vue
<template><div><h2> News头部</h2><br></div></template><script>import bus from '../src/bus'export default {mounted(){bus.$on('data2news',function (shuJu) {console.log(shuJu);});}}</script>

结果:

attrs/attrs/ attrs/listeners:多级组件间传值

  • $attrs:将父组件中不包含props的属性传入子组件,通常配合interitAttrs选项一起使用
  • $listeners:监听子组件中数据的变化,传递给父组件

示例:$attrs
第一步:App.vue

<template><div id="app"><h2>最外层组件</h2><v-parent :msgA="msg1" :msgB="msg2" :msgC="msg3"></v-parent></div></template><script>// 引入子组件import Parent from './views/Parent'export default {name: 'Parent',components: {'v-parent': Parent},data () {return {msg1: 'aaaaa',msg2: 'bbbbb',msg3: 'ccccc'}}}</script>

第二步:Parent.vue

<template><div><h2>中间组件</h2><h-child v-bind="$attrs"></h-child></div></template><script>// 引入子组件import HChild from './Child'export default {name: 'Parent',components: {HChild}}</script>

第三步:Child.vue

<template><div><h2> 数据接收方 </h2><br></div></template><script>export default {mounted () {console.log(this.$attrs)}}</script>

结果: