組件通訊包括:父子組件間的通信和兄弟組件間的通信。在組件化系統構建中,組件間通信必不可少的 (vuex以后再說)。
父組件--> 子組件
1. 屬性設置
父組件關鍵代碼如下:
1 <template> 2 <Child :child-msg="msg"></Child> 3 </template>
子組件關鍵代碼如下:
1 export default { 2 name: 'child', 3 props: { 4 child-msg: String 5 } 6 };
child-msg 為父組件給子組件設置的額外屬性值,屬性值需在子組件中設置props,子組件中可直接使用child-msg變量。
2. 子組件調用父組件
子組件通過 $parent 獲得父組件,通過 $root 獲得最上層的組件。
子組件--> 父組件
1. 發送事件/監聽事件
子組件中某函數內發送事件:
this.$emit('toparentevent', 'data');
父組件監聽事件:
<Child @toparentevent="toparentevent"></Child> // 在methods里接收 methods: { toparentevent(msg) { // msg就是傳遞的數據 console.log(msg) } }
toparentevent 為子組件自定義發送事件名稱,父組件中@toparentevent為監聽事件,toparentevent為父組件處理方法。
2. 父組件直接獲取子組件屬性或方法
給要調用的子組件起個名字。將名字設置為子組件 ref 屬性的值。
<!-- 子組件。 ref的值是組件引用的名稱 --> <child-component ref="aName"></child-component>
父組件中通過 $refs.組件名 來獲得子組件,也就可以調用子組件的屬性和方法了。
// 獲取child.屬性
this.$refs.aName.child
// 調用child.方法()
this.$refs.aName.child()
父組件通過 $children 可以獲得所有直接子組件(父組件的子組件的子組件不是直接子組件)。需要注意 $children 並不保證順序,也不是響應式的。
eventBus中央通信
各組件可自己定義好組件內接收外部組件的消息事件即可,不用理會是哪個組件發過來;而對於發送事件的組件,亦不用理會這個事件到底怎么發送給我需要發送的組件。
先設 main.js 置Bus
// main.js中 new Vue({ el: '#app', router, template: '<App/>', components: { App }, data: { eventBus: new Vue() } })
組件內監聽事件:
1 created() { 2 this.$root.eventBus.$on('childa-message', function(data) { 3 console.log(data); 4 }); 5 }
發送事件的組件:
this.$root.eventBus.$emit('childa-message', this.data)
可能存在如下問題:
1.第一次觸發的時候頁面中的on事件沒有被觸發
2. 為什么后面再一次依次去觸發的時候會出現,每一次都會發現好像之前的on事件分發都沒有被撤銷一樣,導致每一次的事件觸發執行越來越多
解答:
1. 當我們還在頁面A的時候,頁面B還沒生成,也就是頁面B中的 created中所監聽的來自於A中的事件還沒有被觸發。這個時候當你A中emit事件的時候,B其實是沒有監聽到的,
當你從頁面A到頁面B跳轉的時候,發生了什么?首先是先B組件先created然后beforeMount接着A組件才被銷毀,A組件才執行beforeDestory,以及destoryed
所以,我們可以把A頁面組件中的emit事件寫在beforeDestory中去。因為這個時候,B頁面組件已經被created了,也就是我們寫的$on事件已經觸發了
修改如下:在beforeDestory生命周期里,$emit事件
1 beforeDestroy () { 2 this.$root.eventBus.$emit('child-message',this.data) 3 }
2. 因為B頁面$on事件是不會自動清楚銷毀的,需要我們手動來銷毀,所以我在B組件頁面中添加Bus.$off來關閉,銷毀后就不存在執行多次的情況了 。代碼如下:
1 // 在B組件頁面中添加以下語句,在組件beforeDestory的時候銷毀。 2 beforeDestroy () { 3 this.root.eventBus.$off('child-message')
4 },
總結: 所以,要用eventBus 來進行頁面組件之間的數據傳遞,需要注意亮點,組件A$emit事件應在beforeDestory生命周期內。其次,組件B內的$on記得要銷毀。