vue的通信方式(二)---祖父孫三個級別的之間的隔代通信


在之前的文章中我們提到了vue常用的幾種通信方式,如父子,子父,以及兄弟組件之間的通信,可以通過這個傳送門了解他們:Vue通信方式(一)

當我們如果遇到祖組件,父組件,孫組件,三個級別嵌套時,我們該怎么在祖組件與孫組件之間通信呢,當然通過本地存儲或者Vuex都可以實現,但僅僅是一個值得時候未免有點小題大做了,或者是組件之間的通信那樣一級一級傳?有點麻煩,在此,我們就詳解如何實現祖孫之間的通信。

首先我們來看看vue新增的兩個屬性:$attrs和$listeners,這是vue2.4新增的兩個屬性,我們來看看官方文檔是怎么解釋的吧。

好吧,對於第一次看的童鞋來說,並不知道他在BB什么, 簡要的講就是,$attrs可以獲取父作用域傳入的值(不包括props中的),$listeners相當於父作用域的事件監聽器,那我們就可以用這兩個屬性實現祖孫之間的數據通信

首先,我們定義一個祖級別的組件:father1.vue

<template>
    <h6>父組件:
        <p>這是來自c組件的數據:{{msg1}}</p>
       <div>
          <B :messagec="messagec" :msgc="msgc2" v-on:getCData="getCData"></B>
        </div>
    </h6>
</template>
 
<script>
    import B from './son.vue'
    export default{
        data() {
             return {
                messagec:{a:1,c:2}, //傳遞給c組件的數據,可以傳對象,字符串以及其他類型
                msg:'',
                msg1:'',
                msgc2:'第二個傳給孫組件的值'
            }
        },
        components:{
            B
        },
        methods:{
            //執行C子組件觸發的事件
            getCData(val){
                console.log("這是來自C組件的數據:"+val)
                this.msg1=val
            }
        }
    }
</script>

然后在定義一個父級別的組件:son.vue,相當於祖孫通信之間的中間件

<template>
    <h1>這是子組件:
      <div>
          <p>這是B組件</p>
        <!-- C組件中能直接觸發getCData的原因在於 B組件調用C組件時 使用 v-on 綁定了$listeners 屬性 -->
        <!-- 通過v-bind 綁定$attrs屬性,C組件可以直接獲取到A組件中傳遞下來的props(除了B組件中props聲明的) -->
        <C v-bind="$attrs" v-on="$listeners"></C>
      </div>
    </h1>
</template>
 
<script>
    import C from './c.vue' // 引入C組件
    export default{
        data(){
             return {
                mymessage:''
            }
        },
        components:{
            C
        },
        props:{
//            messagec:String // 當在這個組件聲明了傳向C組件的值時,C組件則通過$attrs.messagec得不到該值,相當於被攔截了,要傳給C,則不能在此聲明
        },
        methods:{
        }
    }
</script>

主要是綁定兩個屬性v-bind="$attrs" v-on="$listeners",並且不能在props中聲明傳入的值,"$attrs"用於接受father.vue傳入的值,$listeners用於監聽觸發事件傳值給father.vue.

最后我們定義一個孫級別的組件:c.vue

<template>
    <h1>這是C組件:
      <p>接受來自father的值:{{$attrs.messagec.a}}</p>
      <p>接受來自father第二個的值:{{$attrs.msgc}}</p>
      <input type="text" v-model="msgtofather" @input="passCData(msgtofather)">
    </h1>
</template>
 
<script>
    export default{
        data(){
            return{
                msgtofather:'' //傳給father組件的值
            }
        },
        props:{
//            messagec:String // 當在這個組件聲明了傳向C組件的值時,C組件則通過$attrs.messagec得不到該值,相當於被攔截了,要傳給C,則不能在此聲明
        },
         methods:{
            passCData(val){
                //觸發父組件father中的事件
                this.$emit('getCData',val)
            }
        }
    }
</script>

注意:此組件中props也不能聲明父組件傳入的值,否則$attrs.messagec.a會取不到該值,並且可以接受多個來自祖組件的值

最后,組件通信的測試圖如下:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM