vue 兄弟組件是如何通信的


今天面試被問到這個問題,我自己思考的是讓父組件做兩個子組件之間的橋梁,但是我並沒有去說,感覺是有些low啊,面試完了趕緊查查是怎么通信的;

就是我自己設想的這種方法也是解決問題的一種方法;

兄弟組件通訊

在Vue中實現兄弟組件的通訊也有幾種方法,其中一種方法是讓父組件允當兩個子組件之間的中間件(中繼);

另一種就是使用EventBus(事件總線),它允許兩個子組件之間直接通訊,而不需要涉及父組件。

這里就要好好了解下EventBus(事件總線)的概念了;

1、通過父組件進行兄弟組件之間通訊

先來看第一個方法,就是讓兄弟組件通過一個共同的父組件彼此通訊。

我們還是通過示例來學習。接下來的這個示例包含父組件和兩個子組件,這兩個子組件是兄弟組件。單擊兄弟組件上的按鈕,可以看到他們之間可以相互通訊。

 

 

 首先創建ParentCard組件:

 1 <!-- ParentCard.vue -->
 2 
 3 <template>
 4 
 5   <div class="card">
 6 
 7     <div class="card-header">
 8 
 9       <h5 v-text="theCardTitle"></h5>
10 
11       <button @click="momSaidChill" v-if="stopFighting()" class="btn">停止通訊</button>
12 
13     </div>
14 
15     <div class="card-body">
16 
17       <brother-card :messageSon="messageson" @brotherSaid="messageDaughter($event)"></brother-card>
18 
19       <sister-card :messageDaughter="messagedaughter" @sisterSaid="messageSon($event)"></sister-card>
20 
21     </div>
22 
23   </div>
24 
25 </template>
26 
27 <script>
28 
29 import BrotherCard from './BrotherCard';
30 
31 import SisterCard from './SisterCard'
32 
33 export default {
34 
35   name: 'ParentCard',
36 
37   data: () => ({
38 
39     theCardTitle: '父組件',
40 
41     messagedaughter:'',
42 
43     messageson:''
44 
45   }),
46 
47   components: {
48 
49     BrotherCard,
50 
51     SisterCard
52 
53   },
54 
55   methods: {
56 
57     messageDaughter(message) {
58 
59       this.messagedaughter = message;
60 
61     },
62 
63     messageSon(message) {
64 
65       this.messageson = message;
66 
67     },
68 
69     stopFighting() {
70 
71       if (this.messagedaughter && this.messageson) {
72 
73         return true
74 
75       }
76 
77       return false
78 
79     },
80 
81     momSaidChill() {
82 
83       this.messagedaughter = '',
84 
85       this.messageson = ''
86 
87     }
88 
89   }
90 
91 }; 
92 
93 </script>

 

創建SisterCard組件:

 1 <!-- SisterCard.vue -->
 2 
 3 <template>
 4 
 5   <div class="message">
 6 
 7     <div class="message-header">
 8 
 9       <h5 v-text="theCardTitle"></h5>
10 
11     </div>
12 
13     <div class="message-body">
14 
15       <p class="message-text">我是Sister組件</p>
16 
17       <button @click="messageBrother" class="btn">給哥哥發消息</button>
18 
19       <div v-if="messageDaughter" class="alert" v-html="messageDaughter"></div>
20 
21     </div>
22 
23   </div>
24 
25 </template>
26 
27 <script>
28 
29 export default {
30 
31   name: 'SisterCard',
32 
33   props: ['messageDaughter'],
34 
35   data: () => ({
36 
37     theCardTitle: '子組件2'
38 
39   }),
40 
41   methods: {
42 
43     messageBrother() {
44 
45       this.$emit('sisterSaid', '媽媽說,該做作業了!(^_^)!!!')
46 
47     }
48 
49   }
50 
51 }
52 
53 </script>

 

 

接着創建BrotherCard組件:

 1 <!-- BrotherCard.vue -->
 2 
 3 <template>
 4 
 5   <div class="message">
 6 
 7     <div class="message-header">
 8 
 9       <h5 v-text="theCardTitle"></h5>
10 
11     </div>
12 
13     <div class="message-body">
14 
15       <p class="message-text">我是Brother組件</p>
16 
17       <button @click="messageSister" class="btn">給妹妹發消息</button>
18 
19       <div v-if="messageSon" class="alert" v-html="messageSon"></div>
20 
21     </div>
22 
23   </div>
24 
25 </template>
26 
27 <script>
28 
29 export default {
30 
31   name: 'BrotherCard',
32 
33   props: ['messageSon'],
34 
35   data: () => ({
36 
37     theCardTitle: '子組件1'
38 
39   }),
40 
41   methods: {
42 
43     messageSister() {
44 
45       this.$emit('brotherSaid', '媽媽說,該做作業了!(^_^)!!!')
46 
47     }
48 
49   }
50 
51 }
52 
53 </script>

 

最終效果如下:

接下來簡單看看這個實現過程。

SisterCard通過ParentCardBrotherCard通訊

首先來看SisterCard是如何與BrotherCard通訊的。從示例中可以看出,他們兩之間的通訊是通過其父組件ParentCard作為中間媒介來進行通訊的。

我們在SisterCard組件的<template>中為messageBrother()方法設置了一個@click事件來監聽該事件。

<button @click="messageBrother" class="btn">給哥哥發消息</button>

當用戶點擊SisterCard中的“給哥哥發消息”將會觸發messageBrother()方法。在這個方法中,將發出一個sisterSaid事件,並且把媽媽說,該做作業了!(^_^)!!!信息發送出去。

1 methods: {
2 
3   messageBrother() {
4 
5     this.$emit("sisterSaid", "媽媽說,該做作業了!(^_^)!!!");
6 
7   } 
8 
9 }

 

ParentCard<template>中定制了一個@sisterSaid事件偵聽器,它觸發了messageSon()方法。所以父組件在這兩個兄弟組件之間起到了傳遞的作用。

<sister-card :messageDaughter="messagedaughter" @sisterSaid="messageSon($event)"></sister-card>

另外在ParentCard組件中聲明了messageSon()方法,該方法接受上面發送的自定義事件,並將其設置為messageson屬性。

這樣一來,ParentCard組件中messageson就由空字符串變成了媽媽說,該做作業了!(^_^)!!!

接着在ParentCard組件自定義標簽<brother-card>通過:messageSon="messageson"的方式將messageson屬性綁定到<brother-card>

<brother-card :messageSon="messageson" @brotherSaid="messageDaughter($event)"></brother-card>

這個時候在BrotherCard組件中設置props的屬性值為messageSon。這樣就可以訪問源自於SisterCard組件的數據,並且該數據在BrotherCard中顯示。

props: ["messageSon"],

最后在BrotherCard組件就可以使用該數據。我們可以通過v-if指令來查看messageSon是否有任何有用的數據,如果有,那么就在div.alert中顯示該消息:

<div v-if="messageSon" class="alert" v-html="messageSon"></div>

上面的描述過程也適用於BrotherCard通過ParentCardSisterCard進行數據通訊。

 

2、通過EventBus進行兄弟間組件通訊

隨着應用程序越來越龐大,通過父組件來傳遞所有內容會把事情變得越來越棘手。不過我們還有另一種選擇,那就是使用EventBus架起兄弟之間通訊的橋梁。接下來看看我們是如何利用這一點一完成兄弟組件之間的數據通訊。

我們同樣基於上面的示例來做修改。接下來的示例中,ParentCard組件包含了SisterCardBrotherCard兩個子組件,而且這兩個子組件是兄弟組件。

首先在main.js文件中定義一個新的eventBus對象,其實他是一個全新的Vue實例:

 1 // main.js
 2 
 3 import Vue from 'vue'
 4 
 5 import App from './App'
 6 
 7 export const eventBus = new Vue()
 8 
 9 new Vue({
10 
11   el: '#app',
12 
13   render: h => h(App)
14 
15 })

 

接着在新創建的BrotherCard組件導入main.js

1 <!-- BrotherCard.vue -->
2 
3 <script>
4 
5 import { eventBus } from '../main'
6 
7 </script>

 

eventBus實例現在將成為BrotherCard組件中發出事件的實例。現在我們可以使用eventBus.$emit來替代上例中的this.$emiteventBus是一個Vue實例,而且eventBus有這個$emit方法,這就是我們能夠這么用的原因。這樣做同樣會觸發相同的自定義事件名稱和消息。

1 methods: {
2 
3   messageSister() {
4 
5     eventBus.$emit('brotherSaid', '媽媽說,該做作業了!(^_^)!!!')
6 
7   }
8 
9 } 

同樣可以在SisterCard組件中引入eventBus

<script>

import { eventBus } from '../main'

</script>

created()生命周期鈎子添加到SisterCard組件。在created()鈎子中添加eventBus啟動自定義事件的偵聽器。當使用SisterCard組件時,該偵聽器將開始運行並且會保持運行。下面的代碼只是偵聽brotherSaid自定義事件,然后觸發回調,將作為自定義事件有效負載傳遞的消息分配給fromBrother

1 created() {
2 
3   eventBus.$on('brotherSaid', (message) => {
4 
5     this.fromBrother = message
6 
7   })
8 
9 } 

這樣就可以有條件地顯示來自BrotherCard的信息:

<div v-if="fromBrother" class="alert" v-html="fromBrother"></div>

上面看到的是如何通過eventBus實現SisterCardBrotherCard傳遞數據的方式,反之,BrotherCard向SisterCard`傳遞數據也可以使用類似的方式。

最終代碼如下:

 1 <!-- SisterCard.vue -->
 2 
 3 <template>
 4 
 5   <div class="message">
 6 
 7     <div class="message-header">
 8 
 9       <h5 v-text="theCardTitle"></h5>
10 
11     </div>
12 
13     <div class="message-body">
14 
15       <p class="message-text">我是Sister組件</p>
16 
17       <button @click="messageBrother" class="btn">給哥哥發消息</button>
18 
19       <div v-if="fromBrother" class="alert" v-html="fromBrother"></div>
20 
21     </div>
22 
23   </div>
24 
25 </template>
26 
27 <script>
28 
29 import { eventBus } from "../main";
30 
31 export default {
32 
33   name: "SisterCard",
34 
35   data: () => ({
36 
37     theCardTitle: "Sister Card",
38 
39     fromBrother: ""
40 
41   }),
42 
43   methods: {
44 
45     messageBrother() {
46 
47       eventBus.$emit("sisterSaid", "媽媽說,該做作業了!(^_^)!!!");
48 
49     }
50 
51   },
52 
53   created() {
54 
55     eventBus.$on("brotherSaid", message => {
56 
57       this.fromBrother = message;
58 
59     });
60 
61   }
62 
63 };
64 
65 </script>
 1 <!-- BrotherCard.vue -->
 2 
 3 <template>
 4 
 5   <div class="message">
 6 
 7     <div class="message-header">
 8 
 9       <h5 v-text="theCardTitle"></h5>
10 
11     </div>
12 
13     <div class="message-body">
14 
15       <p class="message-text">我是Brother組件</p>
16 
17       <button @click="messageSister" class="btn">給妹妹發消息</button>
18 
19       <div v-if="fromSister" class="alert" v-html="fromSister"></div>
20 
21     </div>
22 
23   </div>
24 
25 </template>
26 
27 <script>
28 
29 import { eventBus } from "../main.js";
30 
31 export default {
32 
33   name: "BrotherCard",
34 
35   data: () => ({
36 
37     theCardTitle: "Brother Card",
38 
39     fromSister: ""
40 
41   }),
42 
43   methods: {
44 
45     messageSister() {
46 
47       eventBus.$emit("brotherSaid", "媽媽說,該做作業了!(^_^)!!!");
48 
49     }
50 
51   },
52 
53   created() {
54 
55     eventBus.$on("sisterSaid", message => {
56 
57       this.fromSister = message;
58 
59     });
60 
61   }
62 
63 };
64 
65 </script>

 

最后創建的ParentCard組件,我們可以像下面這樣編碼:

 1 <!-- ParentCard -->
 2 
 3 <template>
 4 
 5   <div class="card">
 6 
 7     <div class="card-header">
 8 
 9       <h5 v-text="theCardTitle"></h5>
10 
11     </div>
12 
13     <div class="card-body">
14 
15       <brother-card></brother-card>
16 
17       <sister-card></sister-card>
18 
19     </div>
20 
21   </div>
22 
23 </template>
24 
25 <script>
26 
27 import BrotherCard from "./BrotherCard";
28 
29 import SisterCard from "./SisterCard";
30 
31 export default {
32 
33   name: "ParentCard",
34 
35   data: () => ({
36 
37     theCardTitle: "Parent Card"
38 
39   }),
40 
41   components: {
42 
43     BrotherCard,
44 
45     SisterCard
46 
47   }
48 
49 };
50 
51 </script>

 

總結

在本教程中,我們學習了在Vue中如何實現組件之間的通訊。通過實例看到了如何實現父組件向子組件,子組件向父組件以及兄弟組件間的數據通訊。簡單的根據為:

  • 通過props可以實現父組件向子組件發送數據
  • 通過自定義事件可以實現子組件向父組件發送數據
  • 兄弟組件數據通訊除了借助共同的父組件做為通訊橋梁之外,還可以通過eventBus來讓兄弟之間組件進行數據通訊

最后用一張圖來簡單的描述一下:

 

原文: https://www.w3cplus.com/vue/component-communication.html 

 ps:希望大家早日成為前端大神,哈哈哈


 


免責聲明!

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



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