1. 程式人生 > 實用技巧 >vue 兄弟元件是如何通訊的

vue 兄弟元件是如何通訊的

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

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

兄弟元件通訊

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

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

這裡就要好好了解下EventBus(事件匯流排)的概念了;

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

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

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

首先建立ParentCard元件:

<!-- ParentCard.vue -->

<template>

  <div class="card">

    <div class="card-header">

      <h5 v-text="theCardTitle"></h5>

      <button @click="momSaidChill" v-if="stopFighting()" class="btn">停止通訊</button>

    </div>

    <div class="card-body">

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

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

    </div>

  </div>

</template>

<script>

import BrotherCard from './BrotherCard';

import SisterCard from './SisterCard'

export default {

  name: 'ParentCard',

  data: () => ({

    theCardTitle: '父元件',

    messagedaughter:'',

    messageson:''

  }),

  components: {

    BrotherCard,

    SisterCard

  },

  methods: {

    messageDaughter(message) {

      this.messagedaughter = message;

    },

    messageSon(message) {

      this.messageson = message;

    },

    stopFighting() {

      if (this.messagedaughter && this.messageson) {

        return true

      }

      return false

    },

    momSaidChill() {

      this.messagedaughter = '',

      this.messageson = ''

    }

  }

};

</script>

建立SisterCard元件:

<!-- SisterCard.vue -->

<template>

  <div class="message">

    <div class="message-header">

      <h5 v-text="theCardTitle"></h5>

    </div>

    <div class="message-body">

      <p class="message-text">我是Sister元件</p>

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

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

    </div>

  </div>

</template>

<script>

export default {

  name: 'SisterCard',

  props: ['messageDaughter'],

  data: () => ({

    theCardTitle: '子元件2'

  }),

  methods: {

    messageBrother() {

      this.$emit('sisterSaid', '媽媽說,該做作業了!(^_^)!!!')

    }

  }

}

</script>

接著建立BrotherCard元件:

<!-- BrotherCard.vue -->

<template>

  <div class="message">

    <div class="message-header">

      <h5 v-text="theCardTitle"></h5>

    </div>

    <div class="message-body">

      <p class="message-text">我是Brother元件</p>

      <button @click="messageSister" class="btn">給妹妹發訊息</button>

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

    </div>

  </div>

</template>

<script>

export default {

  name: 'BrotherCard',

  props: ['messageSon'],

  data: () => ({

    theCardTitle: '子元件1'

  }),

  methods: {

    messageSister() {

      this.$emit('brotherSaid', '媽媽說,該做作業了!(^_^)!!!')

    }

  }

}

</script>

最終效果如下:

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

SisterCard通過ParentCardBrotherCard通訊

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

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

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

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

methods: {

  messageBrother() {

    this.$emit("sisterSaid", "媽媽說,該做作業了!(^_^)!!!");

  }

}

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例項:

// main.js

import Vue from 'vue'

import App from './App'

export const eventBus = new Vue()

new Vue({

  el: '#app',

  render: h => h(App)

})

接著在新建立的BrotherCard元件匯入main.js

<!-- BrotherCard.vue -->

<script>

import { eventBus } from '../main'

</script>

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

methods: {

  messageSister() {

    eventBus.$emit('brotherSaid', '媽媽說,該做作業了!(^_^)!!!')

  }

}

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

<script>

import { eventBus } from '../main'

</script>

created()生命週期鉤子新增到SisterCard元件。在created()鉤子中新增eventBus啟動自定義事件的偵聽器。當使用SisterCard元件時,該偵聽器將開始執行並且會保持執行。下面的程式碼只是偵聽brotherSaid自定義事件,然後觸發回撥,將作為自定義事件有效負載傳遞的訊息分配給fromBrother

created() {

  eventBus.$on('brotherSaid', (message) => {

    this.fromBrother = message

  })

}

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

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

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

最終程式碼如下:

<!-- SisterCard.vue -->

<template>

  <div class="message">

    <div class="message-header">

      <h5 v-text="theCardTitle"></h5>

    </div>

    <div class="message-body">

      <p class="message-text">我是Sister元件</p>

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

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

    </div>

  </div>

</template>

<script>

import { eventBus } from "../main";

export default {

  name: "SisterCard",

  data: () => ({

    theCardTitle: "Sister Card",

    fromBrother: ""

  }),

  methods: {

    messageBrother() {

      eventBus.$emit("sisterSaid", "媽媽說,該做作業了!(^_^)!!!");

    }

  },

  created() {

    eventBus.$on("brotherSaid", message => {

      this.fromBrother = message;

    });

  }

};

</script>

<!-- BrotherCard.vue -->

<template>

  <div class="message">

    <div class="message-header">

      <h5 v-text="theCardTitle"></h5>

    </div>

    <div class="message-body">

      <p class="message-text">我是Brother元件</p>

      <button @click="messageSister" class="btn">給妹妹發訊息</button>

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

    </div>

  </div>

</template>

<script>

import { eventBus } from "../main.js";

export default {

  name: "BrotherCard",

  data: () => ({

    theCardTitle: "Brother Card",

    fromSister: ""

  }),

  methods: {

    messageSister() {

      eventBus.$emit("brotherSaid", "媽媽說,該做作業了!(^_^)!!!");

    }

  },

  created() {

    eventBus.$on("sisterSaid", message => {

      this.fromSister = message;

    });

  }

};

</script>

最後建立的ParentCard元件,我們可以像下面這樣編碼:

<!-- ParentCard -->

<template>

  <div class="card">

    <div class="card-header">

      <h5 v-text="theCardTitle"></h5>

    </div>

    <div class="card-body">

      <brother-card></brother-card>

      <sister-card></sister-card>

    </div>

  </div>

</template>

<script>

import BrotherCard from "./BrotherCard";

import SisterCard from "./SisterCard";

export default {

  name: "ParentCard",

  data: () => ({

    theCardTitle: "Parent Card"

  }),

  components: {

    BrotherCard,

    SisterCard

  }

};

</script>

總結

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

  • 通過props可以實現父元件向子元件傳送資料
  • 通過自定義事件可以實現子元件向父元件傳送資料
  • 兄弟元件資料通訊除了藉助共同的父元件做為通訊橋樑之外,還可以通過eventBus來讓兄弟之間元件進行資料通訊

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

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

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