Vue $emit() 方法
使用 Vue 內建的 $emit()
方法,我們可以在子元件中建立一個自定義事件,該事件可以在父元素中捕獲。
Props 用於將資料從父元素髮送到子元件,而 $emit()
則用於做相反的事情:將資訊從子元件傳遞到父元件。
下一步的目的是讓食物項的“收藏”狀態在父元件 App.vue
中更改,而不是像現在這樣在 FoodItem.vue
子元件中發生更改。
將收藏狀態更改的原因是在 App.vue
中而不是在 FoodItem.vue
中,是因為 App.vue
是收藏狀態最初儲存的地方,所以需要更新。在一個更大的專案中,資料可能來自我們與 App.vue
連線的資料庫,並且我們希望透過元件的更改來修改資料庫,所以我們需要從子元件通訊回父元件。
發出自定義事件
需要將資訊從元件傳送到父元件,我們使用內建方法 $emit()
來實現。
我們在 FoodItem.vue
元件的 toggleFavorite
方法中已經處理了點選切換按鈕時需要傳送資訊。現在,讓我們刪除現有的行,並新增一行來發出我們的自定義事件 'toggle-favorite'。
FoodItem.vue
:
methods: {
toggleFavorite() {
this.foodIsFavorite = !this.foodIsFavorite;
this.$emit('toggle-Favorite');
}
}
我們可以選擇自定義事件的名稱,但通常使用 kebab-case 來命名 emit 事件。
接收 emit 事件
自定義 emit 事件 'toggle-favorite' 現在從 FoodItem.vue
元件發出,但我們需要在 App.vue
父元件中監聽該事件,並呼叫一個方法來執行一些操作,以便我們能看到事件已經發生。
我們在 App.vue
中建立元件的地方,使用簡寫 @
而不是 v-on:
來監聽事件。
示例
監聽 App.vue
中的 'toggle-favorite' 事件
<food-item
v-for="x in foods"
:key="x.name"
:food-name="x.name"
:food-desc="x.desc"
:is-favorite="x.favorite"
@toggle-favorite="receiveEmit"
/>
當我們的自定義 'toggle-favorite' 事件發生時,我們需要在 App.vue
中建立 receiveEmit
方法,以便我們能看到事件已經發生。
methods: {
receiveEmit() {
alert('Hello World!');
}
}
執行示例 »
更改父元件中的食物項“收藏”狀態
我們現在有一個事件,當從子元件點選“收藏”按鈕時,該事件會通知 App.vue
。
當點選“收藏”按鈕時,我們希望在 App.vue
中更改 'foods' 陣列中正確食物項的 'favorite' 屬性。為此,我們將食物項名稱從 FoodItem.vue
傳送到 App.vue
,因為每個食物項的名稱都是唯一的。
FoodItem.vue
:
methods: {
toggleFavorite() {
this.$emit('toggle-favorite', this.foodName);
}
}
我們現在可以在 App.vue
中接收食物項名稱,作為當 'toggle-favorite' 事件發生時呼叫的方法的引數,如下所示。
現在我們知道了哪個食物項被點選了,我們可以在 'foods' 陣列中更新正確食物項的 'favorite' 狀態。
App.vue
:
methods: {
receiveEmit(foodId) {
const foundFood = this.foods.find(
food => food.name === foodId
);
foundFood.favorite = !foundFood.favorite;
}
}
在上面的程式碼中,陣列方法 'find' 遍歷 'foods' 陣列,查詢 name 屬性等於我們點選的食物項的物件,並返回該物件作為 'foundFood'。之後,我們可以將 'foundFood.health' 設定為與之前相反的值,以便它在 true
和 false
之間切換。
在此處瞭解有關 JavaScript 陣列方法 'find' 的更多資訊:這裡。
在此處瞭解有關 JavaScript 箭頭函式的更多資訊:這裡。
現在 'foods' 陣列中的正確食物的“favorite”狀態已更新。唯一剩下的就是更新表示收藏食物的影像。
因為食物項元件已經使用“foods”陣列中的“favorite”狀態建立,並作為 prop 'is-favorite' 從 App.vue
傳送,我們只需要在 FoodItem.vue
中引用該 'isFavorite' prop,並在 v-show
中用於 <img>
元素來更新影像。
<img src="/img_quality.svg" v-show="isFavorite">
我們還可以刪除 FoodItem.vue
中的 'foodIsFavorite' 資料屬性,因為它不再使用。
The 'emits' Option
與我們在 FoodItem.vue
元件中宣告 props 的方式相同,我們也可以使用 Vue 的 'emits' 選項來記錄元件發出的內容。
Props 必須在元件中宣告,而 emits 僅建議記錄。
以下是我們如何在 FoodItem.vue
元件中記錄 emit 的方式。
<script>
export default {
props: ['foodName','foodDesc','isFavorite'],
emits: ['toggle-favorite'],
methods: {
toggleFavorite() {
this.$emit('toggle-favorite', this.foodName);
}
}
};
</script>
當 emit 被記錄時,元件對於其他人來說會更容易使用。