天天看點

vue 擷取父元件裡的ref_Vue使用日記(9):Vue元件之間的通信(二)

有時候我們需要父元件直接通路子元件,子元件直接通路父元件,或者是子元件通路根元件。

官方指出:

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就可以通路到該子元件了。

vue 擷取父元件裡的ref_Vue使用日記(9):Vue元件之間的通信(二)

說明:上面所說的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狀态管理的說明。