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
留言分享你的想法!
avatar-img
卡關的人生
2會員
73內容數
分享生活趣事~
卡關的人生的其他內容
2024/11/10
Vue 提供了多種動畫技術來提升應用程式的互動性,包括基於 CSS 類別的動畫、基於狀態的動畫,以及使用監視器來動畫化數值。基於類別的動畫可通過動態添加 CSS 類別來觸發,像是觸發按鈕搖動效果。基於狀態的動畫則是透過樣式綁定,根據互動動態調整元素的外觀,例如根據滑鼠位置改變背景顏色。
Thumbnail
2024/11/10
Vue 提供了多種動畫技術來提升應用程式的互動性,包括基於 CSS 類別的動畫、基於狀態的動畫,以及使用監視器來動畫化數值。基於類別的動畫可通過動態添加 CSS 類別來觸發,像是觸發按鈕搖動效果。基於狀態的動畫則是透過樣式綁定,根據互動動態調整元素的外觀,例如根據滑鼠位置改變背景顏色。
Thumbnail
2024/11/09
Web Components 是一組網頁原生 API,允許開發者創建可重複使用的自訂元素。Vue 與 Web Components 是互補的技術,Vue 支援整合和創建自訂元素。
Thumbnail
2024/11/09
Web Components 是一組網頁原生 API,允許開發者創建可重複使用的自訂元素。Vue 與 Web Components 是互補的技術,Vue 支援整合和創建自訂元素。
Thumbnail
2024/11/08
Vue 建議使用模板構建應用程式,但在需要 JavaScript 的全程式化功能時,渲染函數可派上用場。渲染函數通過 h() 函數創建 vnode,h 是 hyperscript 的簡寫,能生成 HTML 的 JavaScript。
Thumbnail
2024/11/08
Vue 建議使用模板構建應用程式,但在需要 JavaScript 的全程式化功能時,渲染函數可派上用場。渲染函數通過 h() 函數創建 vnode,h 是 hyperscript 的簡寫,能生成 HTML 的 JavaScript。
Thumbnail
看更多
你可能也想看
Thumbnail
孩子寫功課時瞇眼?小心近視!這款喜光全光譜TIONE⁺光健康智慧檯燈,獲眼科院長推薦,網路好評不斷!全光譜LED、180cm大照明範圍、5段亮度及色溫調整、350度萬向旋轉,讓孩子學習更舒適、保護眼睛!
Thumbnail
孩子寫功課時瞇眼?小心近視!這款喜光全光譜TIONE⁺光健康智慧檯燈,獲眼科院長推薦,網路好評不斷!全光譜LED、180cm大照明範圍、5段亮度及色溫調整、350度萬向旋轉,讓孩子學習更舒適、保護眼睛!
Thumbnail
創作者營運專員/經理(Operations Specialist/Manager)將負責對平台成長及收入至關重要的 Partnership 夥伴創作者開發及營運。你將發揮對知識與內容變現、影響力變現的精準判斷力,找到你心中的潛力新星或有聲量的中大型創作者加入 vocus。
Thumbnail
創作者營運專員/經理(Operations Specialist/Manager)將負責對平台成長及收入至關重要的 Partnership 夥伴創作者開發及營運。你將發揮對知識與內容變現、影響力變現的精準判斷力,找到你心中的潛力新星或有聲量的中大型創作者加入 vocus。
Thumbnail
各位使用 Vue.js 開發的小夥伴們,你們都怎麼實作父子層組件資料的雙向綁定呢?如果你還在寫 prop + emit 的話,不妨進來看看吧。
Thumbnail
各位使用 Vue.js 開發的小夥伴們,你們都怎麼實作父子層組件資料的雙向綁定呢?如果你還在寫 prop + emit 的話,不妨進來看看吧。
Thumbnail
切換頁面卡卡有很多種原因,這裡舉的例子只針對元件太大的情境。 除了想辦法拆分外,還有一個方法就是利用 Vue 的 Async Component。
Thumbnail
切換頁面卡卡有很多種原因,這裡舉的例子只針對元件太大的情境。 除了想辦法拆分外,還有一個方法就是利用 Vue 的 Async Component。
Thumbnail
平常我們在 html 上常看到的例如 v-for、v-model 等等... 也是VUE已經幫我們定義好的指令,而這次我們可以依這自己的需求來建立。 此功能屬於較進階的功能,因此實戰中會比較少見,市面上還是有不少完善的套件能達到同樣效果,建議可以先往這方面察找
Thumbnail
平常我們在 html 上常看到的例如 v-for、v-model 等等... 也是VUE已經幫我們定義好的指令,而這次我們可以依這自己的需求來建立。 此功能屬於較進階的功能,因此實戰中會比較少見,市面上還是有不少完善的套件能達到同樣效果,建議可以先往這方面察找
Thumbnail
我們在實作中,難免會遇到在不同組件中,卻有需求相同的資料格式,因此 mixins 可以達到我們的需求,除了 data 以外也包含了 methods 可以共用,舉例來說,學生資料可能會在,班級跟社團內被使用,當我們要撰寫元件時,就可以省略多餘的 data 定義。
Thumbnail
我們在實作中,難免會遇到在不同組件中,卻有需求相同的資料格式,因此 mixins 可以達到我們的需求,除了 data 以外也包含了 methods 可以共用,舉例來說,學生資料可能會在,班級跟社團內被使用,當我們要撰寫元件時,就可以省略多餘的 data 定義。
Thumbnail
VUE為單向資料流的框架,在鄰近層級之間我們可以依靠 props 由父層向子層來傳遞需要的資料,然而遇到跨層級的架構時,雖然也是可以一層層傳進去,只是這會造成多餘的處理及凌亂的程式碼,因此才有了 "provide" 來解決我們跨層級的需求。 層級展示圖
Thumbnail
VUE為單向資料流的框架,在鄰近層級之間我們可以依靠 props 由父層向子層來傳遞需要的資料,然而遇到跨層級的架構時,雖然也是可以一層層傳進去,只是這會造成多餘的處理及凌亂的程式碼,因此才有了 "provide" 來解決我們跨層級的需求。 層級展示圖
Thumbnail
自訂元件生成位置顧名思義就是可以指定部分HTML區塊渲染在特定的畫面上,即使在不同組件也能把A組件內的部分畫面,展現在B組件上,以下方程式舉例。
Thumbnail
自訂元件生成位置顧名思義就是可以指定部分HTML區塊渲染在特定的畫面上,即使在不同組件也能把A組件內的部分畫面,展現在B組件上,以下方程式舉例。
Thumbnail
Vue.js是一種基於MVVM的前端JavaScript框架,類似的框架有React、Angular等。 架設環境 安裝Visual Studio Code(https://code.visualstudio.com/) 安裝Node.js(https://nodejs.org/en/
Thumbnail
Vue.js是一種基於MVVM的前端JavaScript框架,類似的框架有React、Angular等。 架設環境 安裝Visual Studio Code(https://code.visualstudio.com/) 安裝Node.js(https://nodejs.org/en/
Thumbnail
2023 Vue直播班筆記 - 動態路由Props,接續之前的一般動態路由。分為 "寫死" 及 "彈性" 兩種。
Thumbnail
2023 Vue直播班筆記 - 動態路由Props,接續之前的一般動態路由。分為 "寫死" 及 "彈性" 兩種。
Thumbnail
這系列是我在 2023 六角學院 Vue作品實戰班的筆記,筆記以本人理解的方式記錄。此篇主題為 Slot Props 進階應用 ,其中包含單筆資料、多筆資料。
Thumbnail
這系列是我在 2023 六角學院 Vue作品實戰班的筆記,筆記以本人理解的方式記錄。此篇主題為 Slot Props 進階應用 ,其中包含單筆資料、多筆資料。
Thumbnail
前言 Vue 是一個現代開發框架,擁有完尚的生態系,讓我們可以將須多元件客製化,做出組件,並且可重複利用,高擴充性。在開發組件時,每個組件都擁有自己的生命周期,Vue 組件會偵測每個變數值,是否有變,並且更新內容,今天要一個一個了解 Vue 的生命週期,讓大家有更多認識。 Vue 的生命週期
Thumbnail
前言 Vue 是一個現代開發框架,擁有完尚的生態系,讓我們可以將須多元件客製化,做出組件,並且可重複利用,高擴充性。在開發組件時,每個組件都擁有自己的生命周期,Vue 組件會偵測每個變數值,是否有變,並且更新內容,今天要一個一個了解 Vue 的生命週期,讓大家有更多認識。 Vue 的生命週期
追蹤感興趣的內容從 Google News 追蹤更多 vocus 的最新精選內容追蹤 Google News