有时候我们需要父组件直接访问子组件,子组件直接访问父组件,或者是子组件访问根组件。

官方指出:

1)父组件访问子组件:使用$children或$refs;

2)子组件访问父组件:使用$parent。

1、父组件访问子组件:$children

1)this.$children是一个数组,它包含所有子组件对象;

2)我们这里通过一个遍历,取出所有子组件的message状态。

<div id="app">    <parent-cpn>parent-cpn>div><template id="parentCpn">    <child-cpn1>child-cpn1>    <child-cpn2>child-cpn2>    <button @click="showMessage">显示所有子组件信息<button>template><template id="childCpn1">    <h2>我是子组件一<h2>template><template id="childCpn2">    <h2>我是子组件二<h2>template>Vue.component("parent-cpn",{    template:"#parentCpn",    methods:{        showMessage(){            for(let i=0; i<this.$children.length; i++){                console.log(this.$children[i].message);            }        }    })

说明:这里的message没有写出来,message分别在两个子组件的data里进行定义。这里通过this.$children遍历访问了两个子组件的message。

2、父组件访问子组件:$refs

上面使用的$children存在缺陷:

1)$children是数组类型,访问其中的子组件必须通过索引值;

2)但是当子组件过多时,我们需要拿到其中一个子组件往往不能确定它的索引值。

有时候,我们想明确获取其中一个特定的子组件,这个时候就可以使用$refs。

$refs的使用:

$refs和ref指令是一起使用的。

1)首先,我们通过ref给某一个子组件绑定一个特定的ID;

2)其次,通过this.$refs.ID就可以访问到该子组件了。

element ui 获取父组件属性数据 vue获取父组件ref_vue 获取父组件里的ref

说明:上面所说的ID对应child1和child2,访问的时候通过this.$refs.ID的形式。

3、子组件访问父组件:$parent

如果我们想在子组件中直接访问父组件,可以通过$parent。

注意事项:


尽管在Vue开发中,允许通过$parent来访问父组件,但是在真实开发中尽量不要这样做。 子组件应该尽量避免直接访问父组件的数据,因为这样耦合度太高了。如果我们将子组件放在另外一个组件(父组件)之内,很可能该父组件没有对应的属性,往往会引起问题。 另外,更不应该做的是通过$parent直接修改父组件的状态,因为这样做的话父组件中的状态将变得飘忽不定,很不利于我们的调试和维护。

<div id="app">    <parent-cpn>parent-cpn>div><template id="parentCpn">    <child-cpn>child-cpn>template><template id="childCpn">    <button @click="showParent">显示父组件信息<button>template>Vue.component("parent-cpn",{    template:"#parentCpn",    data(){        return {message:"我是父组件"}    },    components:{        "child-cpn",{            template:"#childCpn",            methods:{                showParent(){                    console.log(this.$parent.message);                }            }        }    }})

说明:通过this.$parent访问父组件的message。

4、非父子组件之间的通信:中央事件总线和Vuex


上面说的都是父子组件间的通信,那如果是非父子组件关系呢? 非父子组件关系包括多个层级的组件关系,也包括兄弟组件的关系。在Vue1.x的时候,可以通过$dispatch和$broadcast完成:

1)$dispatch用于向上级派发事件;

2)$broadcast用于向下级广播事件。


但是在Vue2.x都被取消了,在Vue2.x中的方案是通过中央事件总线Bus,也就是一个中介来完成。通常是将Bus挂载到Vue根实例对象中使用,或者将Bus抽离成Bus.js的形式通过引入的方式使用。


方式一:挂载到Vue根对象中。在子组件中通过this.$root.Bus.$emit()触发,通过this.$root.Bus.$on()监听。

import Vue from 'vue';const Bus = new Vue();var app= new Vue({    el:'#app',   data:{    Bus    }})

方式二:将Bus抽离成Bus.js。同样是在一个组件中通过this.$root.Bus.$emit()触发,通过this.$root.Bus.$on()监听。

Bus.jsimport Vue from 'vue';const Bus = new Vue();export default Bus//组件1import Bus from './Bus';export default {    data() {        return {            ......        }    },    methods: {        ......        Bus.$emit('log', 120);    }}//组件二import Bus from './Bus';export default {    data() {        return {            ......        }    },    mounted() {       Bus.$on('log', content => {          console.log(content);        });    }}

但是这种方案比直接使用Vuex状态管理逊色很多,并且Vuex提供了更多好用的功能,所以这里暂且不讨论事件总线Bus这种方案,后续会进行Vuex状态管理的说明。