首頁 > 軟體

vue中元件之間相互通訊傳值的幾種方法詳解

2022-02-28 13:01:00

vue中元件之間相互通訊傳值的方式

我們在使用vue進行專案開發的時候為了更好地管理專案,我們會把每個功能封裝成一個個的元件,在使用的時候直接引入並且呼叫元件來實現程式碼的複用。

我們在封裝元件的時候經常會留有一些預留的介面,供使用的時候呼叫和傳入不同的資料,這個時候我們就涉及到了元件之前的相互傳值的問題。

我這裡總結了在vue中元件之前相互傳值的方法:

1、子元件和父元件通訊,通過呼叫父元件給元件自定義屬性值來實現

<!--parent.vue-->
<template>
    <div>
        <h4>我是父元件:</h4>
        <p>這是我自己的資料{{num}}</p>
        <!--通過給子元件傳入自定義屬性值,傳資料用v-bind或者簡寫形式:號, 傳方法可以使用v-on或者簡寫@符繫結事件-->
        <child :p-num="num" :p-num2="num2" @changePNum="changeNum" />
    </div>
</template>
<script>
    import child from './child.vue'
    export default{
        name: 'parent',
        data(){
            return{
                num: 10,
                num2: 20
            }
        },
        methods:{
            changeNum(n){
                this.num = n;
            }
        }
    }
</script>
<!--child.vue-->
<template>
    <div>
        <h4>我是子元件:</h4>
        <!--第一種可以使用props物件來接收父級傳過來的屬性-->
        <p>這是通過props接收父級元件傳過來的資料{{ pNum}}</p>
        <!--第二種是通過元素的範例屬性$attrs獲取,沒有唄props接收的剩餘屬性-->
        <p>這是通過元件中的$attrs物件獲取父級元件傳過來的資料{{ $attrs['p-num2']}}</p>
        <!--第三種是通過當前範例中的$parent屬性拿到父級範例物件-->
        <p>這是通過元件中的$attrs物件獲取父級元件傳過來的資料{{ topNum }}</p>
        <button @click="changeNum">通過$emit改變父級的資料</button>
        <button @click="changeNum2">通過$listeners改變父級的資料</button>
        <button @click="changeNum3">通過$parent改變父級的資料</button>
    </div>
</template>
<script>
    export default{
        name: 'child',
        // 第一種可以使用props物件來接收父級傳過來的屬性
        props:{
            // 這裡寫對應的要接收的屬性名以駝峰的形式接收
            pNum: {
                type: Number
            }  
        },
        data(){
            return {
                topNum: 0
            }
        },
        created(){
            // 通過使用範例中的$parent拿到父級元件的範例,然後獲取值
            this.topNum = this.$parent.num;  
        },
        methods:{
            changeNum(){
                // 這裡是通過當前元件中的$emit方法來呼叫父級傳過來的方法,並且可以傳入引數
                this.$emit('changePNum', 40);
            },
            changeNum2(){
                // 通過元件中的$listeners中的儲存的父級傳過來的方法進行呼叫
                this.$listeners.changePNum(50);
            },
            changeNum3(){
                // 通過元件中的$listeners中的儲存的父級傳過來的方法進行呼叫
                this.$parent.changeNum(60);
            }
        }
    }
</script>

上邊的程式碼展示了兩種不同形式的元件之間的通訊方式,父元件傳值方式相同,子元件獲取操作方式不同

1.props/$emit組合方式:子元件通過定義props值拿到父元件傳給子元件的屬性來獲取;子元件通過使用$emit方法呼叫父元件的方法;

2.$attrs/$listeners組合方式:子元件可以通過$attrs屬性中的值拿到父元件傳給子元件的屬性值,它裡邊儲存的是props之外的屬性值;

3.$parent方法獲取父元件中的資料和方法

2、父元件主動獲取子元件資料

<!--parent-->
<template>
    <div>
        <button @click="changeChildANum">通過$refs呼叫子元件方法更改子元件資料</button>
        <button @click="changeChildBNum">通過$children呼叫子元件方法更改子元件資料</button>
        <p>這是獲取的子元件childA的資料:{{childA_num}}</p>
        <p>這是獲取的子元件childB的資料:{{childB_num}}</p>
        <!--這裡通過使用ref把元件範例註冊到當前元件的$refs中-->
        <child-a ref="childA"/>
        <child-b />
    </div>
</template>
<script>
    import childA from './childA.vue';
    import childB from './childA.vue';
    export default{
        components:{
            childA,
            childB
        },
        data(){
            return {
                childA_num: 0,
                childB_num: 0
            }
        },
        created(){},
        mounted(){
            // $refs 和 $children 都是需要在mounted中才能獲取到
            // 這裡通過$refs獲取註冊在裡邊的子元件範例,並且獲取他的資料
            this.childA_num = this.$refs.childA.num
            // 第二種方式通過當前元件範例中的$children獲取子元件範例
            this.childB_num = this.$children[1].num;
        },
        methods:{
            changeChildANum(){
                // 這裡通過使用$refs中的元件範例呼叫元件中的方法
                this.$refs.childA.changeNum();
            },
            changeChildBNum(){
                // 這裡通過使用$refs中的元件範例呼叫元件中的方法
                this.$children[1].changeNum();
            }
        }
    }
</script>
<!--child-->
<template>
    <div></div>
</template>
<script>
    export default{
        name: 'childA',
        data(){
            return{
                num: 10
            }
        },
        methods:{
            changeNum(){
                this.num++;
            }
        }
    }
</script>

1.ref/$refs方式,通過給引入的元件定義一個ref屬性,然後就可以通過$refs結合該屬性值得到當前元件的範例

2.ref/$children屬性,給元件定義ref值後,當前元件範例中會在this.$children中拿到所有定義了ref的元件陣列,我們在通過下標進行獲取某個子元件的方法後者屬性值。

3、使用provide/inject方法實現

<!--parent.vue-->
<template>
    <div>
        <child />
    </div>
</template>
<script>
    import child from './child.vue';
    export default{
        // 通過給父級定義一個provide物件,並且定義成一個函數形式,然後返回一個parentData物件,並且物件指向當前元件的一個資料物件上,這樣相當於都指向一個物件
        provide(){
            return {
                parentData: this.proVideData
            }
        }
        name: 'Parent',
        components:{
            child
        },
        data(){
            return{
                proVideData: {
                    num, 1,
                    changeNum: null
                }
            }
        },
        created(){
            // 然後通過範例化後把需要被子元件呼叫到的方法傳入進去
            this.proVideData.changeNum = this.changeNum;
        },
        methods:{
            changeNum(){
                this.proVideData.num++;
            }
        }
    }
</script>
<!--child.vue-->
<template>
    <div>
        <p>{{parentData.num}}</p>
        <button @click="parFun">呼叫父級的方法</button>
    </div>
</template>
<script>
    export default{
        // 子元件通過inject接到祖先元件中的provide廣播的資料
        inject:['parentData'],
        name: 'child',
        data(){
            return{
            }
        },
        methods:{
           parFun(){
                // 這裡直接執行儲存下來的方法
               this.parentData.changeNun();
           } 
        }
    }
</script>

這種方式適合層級比較深的元件傳值,這裡的基本原理是,通過給祖先元件設定provide屬性,然後把想要傳給後代元件的屬性值,進行儲存;
然後在後代元件中,那個需要拿到傳播的資料,可以給元件本身設定injuct屬性,來接收想要監聽的資料值;

然後就可以進行通訊了

4、使用事件匯流排

此方發可以在任意元件中進行監聽當前定義的方法。來實現,元件間相互通訊

<!--event-bus.js-->
import Vue from 'vue';
// 這裡從建立了一個新的vue範例物件
export const EventBus = new Vue();
<!--parent.vue-->
<template>
    <div>
    </div>
</template>
<script>
// 這裡引入事件匯流排
import { EventBus } from './event-bus';
export default{
    data(){
        return{
            eventBusMsg: ''
        }
    },
    created(){
        // 然後給事件匯流排繫結一個需要監聽的方法,類似於釋出訂閱者的增加訂閱
        EventBus.$on("eventBusMsg", (msg) => {
            console.log(msg);
            this.eventBusMsg = msg;
        });
    },
    beforeDestroy(){
         EventBus.$small("eventBusMsg");
    }
}
</script>
<!--sub.vue後代元件-->
<template>
    <div>
        <button @click="eventBusChange">通過事件匯流排呼叫元件的方法</button>
    </div>
</template>
<script>
// 其他元件也需要你引入該外掛
import { EventBus } from './event-bus';
export default{
    data(){
    },
    created(){
    },
    methods:{
        eventBusChange(){
            //這裡是通過eventBus來呼叫一個訂閱的訊息方法,並傳入值過去
            EventBus.$emit('eventBusMsg', 'childB');
        }
    }
}
</script>

事件匯流排的呼叫方式是:

1.定義一個全域性的vue範例並匯出;

2.然後在需要監聽某個事件的元件中引入event-bus

3.給當前的元件在created方法中增加方法

4.然後子元件可以通過引入event-bus檔案然後通過EventBus.$emit方式執行監聽的時間方法

5、vuexlocalStoragesessionStorage

還可以使用Vuex、本地儲存等方式來實現全域性公用。

總結

本篇文章就到這裡了,希望能夠給你帶來幫助,也希望您能夠多多關注it145.com的更多內容!  


IT145.com E-mail:sddin#qq.com