vue組件之間的通信有很多種方式,最常用到的就是父子組件之間的傳值,但是當項目工程比較大的時候,就會出現兄弟組件之間的傳值,跨級組件之間的傳值。不可否認,這些都可以類似父子組件一級一級的轉換傳遞,但是當項目比較大,功能比較複雜的時候,就會變得比較冗餘,代碼不利於維護;這時候可能會有很多人使用到vue ...
vue組件之間的通信有很多種方式,最常用到的就是父子組件之間的傳值,但是當項目工程比較大的時候,就會出現兄弟組件之間的傳值,跨級組件之間的傳值。不可否認,這些都可以類似父子組件一級一級的轉換傳遞,但是當項目比較大,功能比較複雜的時候,就會變得比較冗餘,代碼不利於維護;這時候可能會有很多人使用到vuex,但是如果項目中多個組件共用狀態比較少,項目比較小,並且全局狀態比較少,好像就沒有使用vuex來管理數據的必要。
一、中央事件匯流排(eventBus)
主要是通過在要相互通信的兄弟組件之中,都註冊引入一個新的vue實例,然後通過分別調用這個實例的事件觸發和監聽來實現通信和參數傳遞,也就是我們常說的bus車事件。
1、首先,全局註冊一個新的vue實例,可以放在我們常用的vue項目文件中
js/event-bus.js
import Vue from 'vue' export default new Vue()
2、如果不想全局引用可以,在使用的vue文件里使用,舉個例子:contentLeft.vue,contentRight.vue 需要將contentLeft.vue與contentRight.vue互相通信
contentLeft.vue
<template> <div> {{message}} <button @click="handleClick">test</button> </div> </template> <script> import bus from '../../assets/js/event-bus' export default { data () { return { message: 'this is content here' } }, props: { con: { type: String } }, components: { descripe }, methods: { handleClick () { bus.$emit('getDate', 'brathers!') } } } </script>
contentRight.vue
<template> <div> {{message}} <p v-for="(item,index) in meslist" :key="index">{{item}}</p> </div> </template> <script> import bus from '../../assets/js/event-bus' export default { data () { return { message: '', meslist: [] } }, created () { bus.$on('getDate', (val) => { console.log(val) this.message = val // this.meslist.push(val) }) }, beforeDestroy () { // 組件銷毀前需要解綁事件。否則會出現重覆觸發事件的問題!!!!!!!!!!!!! bus.$off('getDate') } } </script>
當點擊contentLeft的按鈕的時候,contentRight的message值就獲取到了總left中傳過來的'brothers'
優點:通過bus事件方法可以簡單快捷的進行組件之間的傳值,在項目不大的時候,減少了對vuex的依賴
缺點:1、bus事件對生命周期比較嚴謹,當你bus.$emit發送事件時,如果兄弟組件還不存在,當真正打開兄弟組件時,此時在created裡面bus.$on是監聽不到傳遞的值的
2、bus事件不會隨著組件的關閉而自行銷毀,所以當路由切換時,bus事件會不停的觸發,如果數據量比較多的時候,可能會比較影響性能吧,所以需要及時銷毀所綁定的bus事件
二、跨組件之間的通信
vue2.4之後,跨組件之間的通信可以通過$attr和$listeners來實現
舉個例子,father.vue child.vue grandChild.vue
father.vue組件中傳值
<template> <div class="about"> <p>子組件給父組件傳值,父組件再給父組件傳值</p> <child :con="con" :son="son" @getCData = "getCData" ></child> </div> </template> <script> import child from './components/child' export default { data () { return { test: 'test', con: 'child', son: 'child-child' } }, components: { child }, methods: { getGrandChildData (val) { this.son = val console.log('這是來自grandchild組件的數據:' + val) console.log(this.son) } } } </script>
child.vue組件中設置grandChild組件的$attr和$listner屬性
<template> <div> {{message}} <i class="get-data">{{con}}</i> <grandChild v-bind="$attrs" v-on="$listeners"></grandChild > <button @click="handleClick">test</button> </div> </template> <script> import grandChild from './grandChild ' export default { data () { return { message: 'this is content here' } }, props: { con: { type: String } }, components: { grandChild } } </script>
grandChild.vue組件可以通過$attr監聽到爺爺級組件的值,再通過觸發事件向爺爺級組件傳遞修改值
<template> <div> {{list}} <p class="get-data">{{$attrs.son}}</p> <input type="text" v-model="$attrs.son"> <button @click="passData($attrs.son)">按一下</button> </div> </template> <script> export default { data () { return { list: 'ceshixia' } }, methods: { passData (val) { // 觸發事件,改變值爺爺級組件的值 this.$emit('getGrandChildData', val) } } } </script>
以上就可以實現跨級組件之間的傳值,可以引用到各種場景中去