EP23 - 組件事件

閱讀時間約 1 分鐘
Component Events,上篇的props就好累了~
這次事件感覺更複雜www
本頁假設您已經閱讀過組件基礎。如果您對組件還不熟悉,請先閱讀該部分內容。

發送和監聽事件 - Emitting and Listening to Events​

組件可以使用內建的 $emit 方法在模板表達式中直接發送自定義事件(例如在 v-on 處理器中):

<template>
<!-- MyComponent -->
<button @click="$emit('someEvent')">點擊我</button>
</template>

父組件可以使用 v-on 來監聽該事件:

<template>
<MyComponent @some-event="callback" />
</template>

在組件事件監聽器上也支援 .once 修飾符:

<template>
<MyComponent @some-event.once="callback" />
</template>

像組件和屬性一樣,事件名稱也提供自動大小寫轉換。注意,我們發送了一個駝峰式命名的事件,但在父組件中可以用連字號命名的監聽器來監聽它。與屬性命名一樣,我們建議在模板中使用連字號命名的事件監聽器。

提示

與原生 DOM 事件不同,組件發送的事件不會冒泡。您只能監聽直接子組件發送的事件。如果需要在兄弟或深層嵌套的組件之間進行通信,請使用外部事件總線或全局狀態管理解決方案。

事件參數 - Event Arguments​

有時發送事件時傳遞特定值是有用的。例如,我們可能希望 <BlogPost> 組件負責增加文字的大小。在這些情況下,我們可以傳遞額外的參數給 $emit 來提供這個值:

<template>
<button @click="$emit('increaseBy', 1)">
增加 1
</button>
</template>

然後,在父組件中監聽事件時,我們可以使用內聯箭頭函數作為監聽器,這樣我們就可以訪問事件參數:

<template>
<MyButton @increase-by="(n) => count += n" />
</template>

或者,如果事件處理器是一個方法:

<template>
<MyButton @increase-by="increaseCount" />
</template>

那麼該值將作為該方法的第一個參數傳遞:

function increaseCount(n) {
count.value += n
}

提示

傳遞給 $emit() 的所有額外參數(在事件名稱之後)將被轉發給監聽器。例如,使用 $emit('foo', 1, 2, 3) 時,監聽器函數將接收三個參數。

宣告發出的事件 - Declaring Emitted Events

一個組件可以使用 defineEmits() 巨集,顯式地宣告它將發出的事件:

<script setup>
defineEmits(['inFocus', 'submit'])
</script>

<template> 中使用的 $emit 方法無法在 <script setup> 區塊內訪問,但 defineEmits() 會返回一個等效的函數供我們使用:

<script setup>
const emit = defineEmits(['inFocus', 'submit'])

function buttonClick() {
emit('submit')
}
</script>

defineEmits() 巨集不能在函數內使用,必須直接放置在 <script setup> 內,如上例所示。

如果你使用顯式的 setup 函數而不是 <script setup>,則應使用 emits 選項來宣告事件,並且 emit 函數會在 setup() 上下文中暴露:

export default {
emits: ['inFocus', 'submit'],
setup(props, ctx) {
ctx.emit('submit')
}
}

setup() 上下文的其他屬性一樣,可以安全地解構 emit

export default {
emits: ['inFocus', 'submit'],
setup(props, { emit }) {
emit('submit')
}
}

emits 選項和 defineEmits() 巨集還支持物件語法。如果使用 TypeScript,你可以為參數設置類型,這允許我們在運行時對發送事件的負載進行驗證:

<script setup lang="ts">
const emit = defineEmits({
submit(payload: { email: string, password: string }) {
// 返回 `true` 或 `false` 來指示
// 驗證通過 / 失敗
}
})
</script>

如果你在 <script setup> 中使用 TypeScript,也可以使用純型別註解來宣告發出的事件:

<script setup lang="ts">
const emit = defineEmits<{
(e: 'change', id: number): void
(e: 'update', value: string): void
}>()
</script>

更多詳細信息:Typing Component Emits

雖然是可選的,但建議定義所有發出的事件,以更好地記錄組件的工作方式。這還允許 Vue 排除從fallthrough attribute來的已知的監聽器,避免由第三方代碼手動派發的 DOM 事件引起的邊緣情況。

提示

如果在 emits 選項中定義了本機事件(例如,click),則監聽器現在只會監聽組件發出的 click 事件,不再響應本機 click 事件。

事件驗證 - Events Validation

類似於屬性類型驗證,當發出事件使用物件語法而不是陣列語法時,可以對其進行驗證。

要添加驗證,事件會被分配一個函數,該函數接收傳遞給 emit 調用的參數並返回布林值,以指示事件是否有效。

<script setup>
const emit = defineEmits({
// 無驗證
click: null,

// 驗證提交事件
submit: ({ email, password }) => {
if (email && password) {
return true
} else {
console.warn('無效的提交事件有效載荷!')
return false
}
}
})

function submitForm(email, password) {
emit('submit', { email, password })
}
</script>
事件似乎比較簡單一點~
但還props 跟 emit不都是來傳遞參數的嗎?

props 跟 emit 差異?

在 Vue.js 中,props$emit 是用來在組件之間進行數據和事件傳遞的兩種主要方式,但它們的用途和使用場景有所不同。以下是它們的區別和使用方法:

數據流方向

props:是從父組件向子組件傳遞數據。父組件通過 props 將數據傳遞給子組件,子組件通過接收這些 props 來顯示或處理數據。

$emit:是從子組件向父組件傳遞事件。子組件通過 $emit 發出事件,父組件可以監聽這些事件並根據需要做出相應的處理。

用途

props:用於將靜態或動態數據傳遞給子組件。這些數據可以在子組件中作為讀取狀態或顯示內容。
$emit:用於子組件向父組件傳遞動態行為或事件通知。例如,當用戶在子組件中觸發某個行為(如按鈕點擊)時,子組件可以通過 $emit 通知父組件。

使用 props 傳遞數據

父組件

<template>
<div>
<ChildComponent :message="parentMessage" />
</div>
</template>

<script>
import ChildComponent from './ChildComponent.vue';

export default {
components: { ChildComponent },
data() {
return {
parentMessage: 'Hello from parent'
};
}
};
</script>

子組件

<template>
<div>
<p>{{ message }}</p>
</div>
</template>

<script>
export default {
props: {
message: {
type: String,
required: true
}
}
};
</script>

使用 $emit 傳遞事件

子組件

<template>
<button @click="$emit('customEvent', 'Hello from child')">Click Me</button>
</template>

<script>
export default {
// No props needed in this example
};
</script>

父組件

<template>
<div>
<ChildComponent @custom-event="handleCustomEvent" />
</div>
</template>

<script>
import ChildComponent from './ChildComponent.vue';

export default {
components: { ChildComponent },
methods: {
handleCustomEvent(message) {
console.log(message); // Output: "Hello from child"
}
}
};
</script>

總結

  • props:用於父組件向子組件傳遞數據,確保子組件可以顯示或處理這些數據。
  • $emit:用於子組件向父組件發送事件通知,讓父組件能夠對這些事件進行響應。

這兩者結合使用,可以實現父子組件間的雙向通信,從而構建更加靈活和模組化的 Vue.js 應用程式。

avatar-img
2會員
70內容數
分享生活趣事~
留言0
查看全部
avatar-img
發表第一個留言支持創作者!
卡關的人生 的其他內容
props的值可以是字符串數組或物件語法,每個屬性的鍵是prop的名字,值是預期類型的建構函數。當解構props時,Vue會自動添加props.前綴以保持響應性。Prop驗證確保了數據類型和要求的一致性,使開發更嚴謹。
接下來要深入探討組件註冊的內容!Vue 組件需要註冊,讓 Vue 知道在模板中遇到組件時在哪裡找到實現。註冊方式有全局和局部兩種。全局註冊適用於通用、頻繁使用的組件,例如按鈕、模態框等;而局部註冊適用於特定頁面或功能,能明確依賴關係,提升維護性。回顧之前的範例,我們都是使用局部註冊呢!
Ex6SimpleComponent.vue 使用 ref 來創建響應式變數 groceryList,並引入 TodoItem 子組件。模板部分使用 <ol> 標籤來創建有序列表,並透過 v-for 指令遍歷 groceryList 陣列,每個項目對應一個 TodoItem 組件。
在這個範例中,我們展示了如何使用 Vue 的 v-model 來實現各種表單元件的雙向綁定。範例包括文字輸入框、單選框、多選框、單選按鈕、下拉選單和多選下拉選單。使用 ref 創建響應式變數,並在 template 中使用 v-model 進行雙向綁定。這使得表單元件能夠即時反映和更新數據。
這個範例包含六個基礎範例,接下來的實用範例將會更有趣。第四個範例關於條件與迴圈,實作起來也不難。在介紹這個範例之前,注意到如果組件的 <style> 標籤中缺少 scoped 屬性,樣式會全局生效,影響到其他組件的按鈕樣式。因此,請確保每個組件的樣式都加上 scoped。
範例中,message 用於顯示動態標題,isRed 控制段落顏色的切換,color 用於設定文本顏色。透過點擊事件,使用者可以切換 isRed 和 color 的值。具體來說,當滑鼠懸停在 <span> 上時,會顯示 "Hello World!" 的標題;點擊段落則會改變其顏色。
props的值可以是字符串數組或物件語法,每個屬性的鍵是prop的名字,值是預期類型的建構函數。當解構props時,Vue會自動添加props.前綴以保持響應性。Prop驗證確保了數據類型和要求的一致性,使開發更嚴謹。
接下來要深入探討組件註冊的內容!Vue 組件需要註冊,讓 Vue 知道在模板中遇到組件時在哪裡找到實現。註冊方式有全局和局部兩種。全局註冊適用於通用、頻繁使用的組件,例如按鈕、模態框等;而局部註冊適用於特定頁面或功能,能明確依賴關係,提升維護性。回顧之前的範例,我們都是使用局部註冊呢!
Ex6SimpleComponent.vue 使用 ref 來創建響應式變數 groceryList,並引入 TodoItem 子組件。模板部分使用 <ol> 標籤來創建有序列表,並透過 v-for 指令遍歷 groceryList 陣列,每個項目對應一個 TodoItem 組件。
在這個範例中,我們展示了如何使用 Vue 的 v-model 來實現各種表單元件的雙向綁定。範例包括文字輸入框、單選框、多選框、單選按鈕、下拉選單和多選下拉選單。使用 ref 創建響應式變數,並在 template 中使用 v-model 進行雙向綁定。這使得表單元件能夠即時反映和更新數據。
這個範例包含六個基礎範例,接下來的實用範例將會更有趣。第四個範例關於條件與迴圈,實作起來也不難。在介紹這個範例之前,注意到如果組件的 <style> 標籤中缺少 scoped 屬性,樣式會全局生效,影響到其他組件的按鈕樣式。因此,請確保每個組件的樣式都加上 scoped。
範例中,message 用於顯示動態標題,isRed 控制段落顏色的切換,color 用於設定文本顏色。透過點擊事件,使用者可以切換 isRed 和 color 的值。具體來說,當滑鼠懸停在 <span> 上時,會顯示 "Hello World!" 的標題;點擊段落則會改變其顏色。
你可能也想看
Google News 追蹤
Thumbnail
這個秋,Chill 嗨嗨!穿搭美美去賞楓,裝備款款去露營⋯⋯你的秋天怎麼過?秋日 To Do List 等你分享! 秋季全站徵文,我們準備了五個創作主題,參賽還有機會獲得「火烤兩用鍋」,一起來看看如何參加吧~
Thumbnail
11/20日NVDA即將公布最新一期的財報, 今天Sell Side的分析師, 開始調高目標價, 市場的股價也開始反應, 未來一週NVDA將重新回到美股市場的焦點, 今天我們要分析NVDA Sell Side怎麼看待這次NVDA的財報預測, 以及實際上Buy Side的倉位及操作, 從
Thumbnail
Hi 大家好,我是Ethan😊 相近大家都知道保濕是皮膚保養中最基本,也是最重要的一步。無論是在畫室裡長時間對著畫布,還是在旅途中面對各種氣候變化,保持皮膚的水分平衡對我來說至關重要。保濕化妝水不僅能迅速為皮膚補水,還能提升後續保養品的吸收效率。 曾經,我的保養程序簡單到只包括清潔和隨意上乳液
Thumbnail
各位使用 Vue.js 開發的小夥伴們,你們都怎麼實作父子層組件資料的雙向綁定呢?如果你還在寫 prop + emit 的話,不妨進來看看吧。
Thumbnail
切換頁面卡卡有很多種原因,這裡舉的例子只針對元件太大的情境。 除了想辦法拆分外,還有一個方法就是利用 Vue 的 Async Component。
Thumbnail
一開始你先把你的專案push上去後,修改vite.config.ts ,要在裡面新增  base: "/Cart/" (/放自己的專案名稱/) build: {outDir: "docs"}, 接下來你要去你的github setting 裡面 -> Page ->選Deploy fro
Thumbnail
前言 從零開始構建一個 DateTimePicker 可能看起來令人畏懼,但試想一下你將獲得的靈活性和控制力。在這個系列中,我們將逐步揭開構建過程的神秘面紗,讓您能夠創建一個完全符合需求的自定義 DateTimePicker。 本文章,屬於付費系列的文章,這篇文章,我會希望讀者可以得到的
Thumbnail
在 TypeScript 中,套件是模組化代碼的集合,可以提高代碼的可重用性和可維護性。常見的套件包括各種庫和框架,如 lodash、express 等。以下是有關引用套件、自定義套件和常見套件的詳細介紹。
Thumbnail
套件(Package)是將程式或程式庫進行組織、分發和共享的一種方式。在軟體開發中,套件通常包含了相關的程式碼、資源文件和元數據,並提供了統一的名稱空間和版本管理。
Thumbnail
因為最近想嘗試編碼風格,於是就選了一套比較"不嚴格"的輔助工具來摸索。 編輯器 VS CODE 框架 VUE3 打包工具 VITE 編碼風格 Standard 環境 version { "nodejs":"v18.18.0", "npm":"9.8.1" }
Thumbnail
平常我們在 html 上常看到的例如 v-for、v-model 等等... 也是VUE已經幫我們定義好的指令,而這次我們可以依這自己的需求來建立。 此功能屬於較進階的功能,因此實戰中會比較少見,市面上還是有不少完善的套件能達到同樣效果,建議可以先往這方面察找
Thumbnail
我們在實作中,難免會遇到在不同組件中,卻有需求相同的資料格式,因此 mixins 可以達到我們的需求,除了 data 以外也包含了 methods 可以共用,舉例來說,學生資料可能會在,班級跟社團內被使用,當我們要撰寫元件時,就可以省略多餘的 data 定義。
Thumbnail
這個秋,Chill 嗨嗨!穿搭美美去賞楓,裝備款款去露營⋯⋯你的秋天怎麼過?秋日 To Do List 等你分享! 秋季全站徵文,我們準備了五個創作主題,參賽還有機會獲得「火烤兩用鍋」,一起來看看如何參加吧~
Thumbnail
11/20日NVDA即將公布最新一期的財報, 今天Sell Side的分析師, 開始調高目標價, 市場的股價也開始反應, 未來一週NVDA將重新回到美股市場的焦點, 今天我們要分析NVDA Sell Side怎麼看待這次NVDA的財報預測, 以及實際上Buy Side的倉位及操作, 從
Thumbnail
Hi 大家好,我是Ethan😊 相近大家都知道保濕是皮膚保養中最基本,也是最重要的一步。無論是在畫室裡長時間對著畫布,還是在旅途中面對各種氣候變化,保持皮膚的水分平衡對我來說至關重要。保濕化妝水不僅能迅速為皮膚補水,還能提升後續保養品的吸收效率。 曾經,我的保養程序簡單到只包括清潔和隨意上乳液
Thumbnail
各位使用 Vue.js 開發的小夥伴們,你們都怎麼實作父子層組件資料的雙向綁定呢?如果你還在寫 prop + emit 的話,不妨進來看看吧。
Thumbnail
切換頁面卡卡有很多種原因,這裡舉的例子只針對元件太大的情境。 除了想辦法拆分外,還有一個方法就是利用 Vue 的 Async Component。
Thumbnail
一開始你先把你的專案push上去後,修改vite.config.ts ,要在裡面新增  base: "/Cart/" (/放自己的專案名稱/) build: {outDir: "docs"}, 接下來你要去你的github setting 裡面 -> Page ->選Deploy fro
Thumbnail
前言 從零開始構建一個 DateTimePicker 可能看起來令人畏懼,但試想一下你將獲得的靈活性和控制力。在這個系列中,我們將逐步揭開構建過程的神秘面紗,讓您能夠創建一個完全符合需求的自定義 DateTimePicker。 本文章,屬於付費系列的文章,這篇文章,我會希望讀者可以得到的
Thumbnail
在 TypeScript 中,套件是模組化代碼的集合,可以提高代碼的可重用性和可維護性。常見的套件包括各種庫和框架,如 lodash、express 等。以下是有關引用套件、自定義套件和常見套件的詳細介紹。
Thumbnail
套件(Package)是將程式或程式庫進行組織、分發和共享的一種方式。在軟體開發中,套件通常包含了相關的程式碼、資源文件和元數據,並提供了統一的名稱空間和版本管理。
Thumbnail
因為最近想嘗試編碼風格,於是就選了一套比較"不嚴格"的輔助工具來摸索。 編輯器 VS CODE 框架 VUE3 打包工具 VITE 編碼風格 Standard 環境 version { "nodejs":"v18.18.0", "npm":"9.8.1" }
Thumbnail
平常我們在 html 上常看到的例如 v-for、v-model 等等... 也是VUE已經幫我們定義好的指令,而這次我們可以依這自己的需求來建立。 此功能屬於較進階的功能,因此實戰中會比較少見,市面上還是有不少完善的套件能達到同樣效果,建議可以先往這方面察找
Thumbnail
我們在實作中,難免會遇到在不同組件中,卻有需求相同的資料格式,因此 mixins 可以達到我們的需求,除了 data 以外也包含了 methods 可以共用,舉例來說,學生資料可能會在,班級跟社團內被使用,當我們要撰寫元件時,就可以省略多餘的 data 定義。