Vue3?$emit用法指南(含選項(xiàng)API、組合API及?setup?語(yǔ)法糖)
許多Vue模式涉及使用props
將數(shù)據(jù)從父組件傳遞到子組件。但如果我們需要一個(gè)子組件將數(shù)據(jù)傳給它的父組件呢?
使用 emit
,我們可以觸發(fā)事件并將數(shù)據(jù)傳遞到組件的層次結(jié)構(gòu)中。這對(duì)下面幾種情況很有用,如:
- 從 input 中發(fā)出數(shù)據(jù)
- 從 modal 本身內(nèi)部關(guān)閉 modal
- 父組件響應(yīng)子組件
Vue Emit是如何工作的?
當(dāng)我們 emit 一個(gè)事件時(shí),我們用一個(gè)或多個(gè)參數(shù)調(diào)用一個(gè)方法:
- eventName: string - 事件的名稱
- values: any - 通過(guò)事件傳遞的參數(shù)
下面是一個(gè)內(nèi)聯(lián) emit的例子,<button @click="$emit('add', Math.random())">
。emit一個(gè)名為add
的事件,并將Math.random()
的值作為參數(shù)傳遞出去。
然后,在父組件使用v-on
或@
指令可以監(jiān)聽(tīng)我們的自定義添加事件并接收該參數(shù)值。
Child.vue
<template> <button @click="$emit('add', Math.random())"> Add Math.random() </button> </template>
在** Parent.vue **中監(jiān)聽(tīng):
<script setup> import { ref } from 'vue' const count = ref(0) // 也可以從我們的模板中調(diào)用一個(gè)函數(shù) `<ChildComponent @add="add" /> // const add = (i) => count.value += i </script> <template> <ChildComponent @add="(i) => count += i" /> <p>Count: {{ count }}</p> </template>
每次我們點(diǎn)擊按鈕,Child.vue
都會(huì) emit 一個(gè) add
事件,并帶有一個(gè)0到1之間的隨機(jī)值。 然后,Parent.vue
捕捉到這個(gè)事件,并將這個(gè)值添加到計(jì)數(shù)中。
可以傳遞任意多的參數(shù),監(jiān)聽(tīng)器也會(huì)收到所有的參數(shù):
- Child -
$emit('add', Math.random(), 44, 50)
- Parent -
@add="(i, j, k) => count += i + j + k"
現(xiàn)在,我們知道如何在我們的模板中 emit 內(nèi)聯(lián)事件,但在更復(fù)雜的例子中,如果我們從SFC的script
中 emit 一個(gè)事件會(huì)更好。特別是當(dāng)我們想在 emit 事件之前執(zhí)行一些邏輯時(shí),這很有用。
在Vue 3中,我們有2種不同的方法來(lái)做到這一點(diǎn):
- 選項(xiàng)API -
this.$emit
- 帶有
setup()
的組合API -context.emit
- 帶有
<script setup>
的組合API -defineEmits()
我們一個(gè)一個(gè)來(lái)看。
選項(xiàng)API - this.$emit
在 Vue3 中,我人可以選擇使用選項(xiàng)API或組合API。
在選項(xiàng)API中,我們可以調(diào)用this.$emit
來(lái) emit一個(gè)自定義事件。
看下面這個(gè)例子在 MyTextInput.vue
中,它包含一個(gè) label
和 input
。每當(dāng) input
改變時(shí),我們會(huì) emit 一個(gè)事件,并將輸入的值轉(zhuǎn)成大寫(xiě)作為參數(shù)傳遞出去。
我們可以不從模板中調(diào)用$emit
,而是調(diào)用一個(gè)組件方法。在該方法中調(diào)用this.$emit
并把我們的值傳給它。
MyTextInput.vue
<script> export default { methods: { handleChange (event) { this.$emit("customChange", event.target.value.toUpperCase()) } } } </script> <template> <div> <label>My Custom Input</label> <input type="text" placeholder="Custom input!" @input="handleChange" /> </div> </template>
在 Parent.vue 中接收:
<script> export default { methods: { handleChange (event) { this.$emit("customChange", event.target.value.toUpperCase()) } } } </script> <template> <div> <label>My Custom Input</label> <input type="text" placeholder="Custom input!" @input="handleChange" /> </div> </template>
帶有setup()的組合API - context.emit
在 組合API中,如果使用setup
函數(shù),就不能在用 this
,也就是不能調(diào)用this.$emit()
方法了。
相反,可以使用 setup 方法中的第二個(gè)參數(shù) context
來(lái)訪問(wèn) emit
方法。我們可以用之前使用的事件名稱和值調(diào)用context.emit
。
MyTextInput.vue
<script> export default { // can use the entire context object setup (props, context) { const handleChange = (event) => { context.emit("customChange", event.target.value) } return { handleChange } }, // or we can destructure it and get `emit` setup (props, { emit }) { const handleChange = (event) => { emit("customChange", event.target.value) } return { handleChange } } } </script> <template> <div> <label>My Custom Input</label> <input type="text" placeholder="Custom input!" @input="handleChange" /> </div> </template>
在 <script setup> 中的用法
當(dāng)我們使用<script setup>
時(shí),我們無(wú)法訪問(wèn)組件實(shí)例或 context
上下文參數(shù)。那我們?cè)趺传@得 emit
?
在這種情況下,我們可以使用 defineEmits
:
- 指定組件要 emit 事件
- 為每個(gè)事件添加驗(yàn)證信息
- 可以訪問(wèn)與context.emit相同的值
在最簡(jiǎn)單的情況下,defineEmits
是一個(gè)字符串?dāng)?shù)組,每個(gè)字符串是一個(gè)事件的名稱。
MyTextInput.vue
<script setup> const emit = defineEmits(['customChange']) const handleChange = (event) => { emit('customChange', event.target.value.toUpperCase()) } </script>
然而,如果我們傳遞一個(gè)對(duì)象,我們可以為每個(gè)事件添加一個(gè)驗(yàn)證器函數(shù),我們可以在里面檢查值是否是我們所需要的格式。
像事件監(jiān)聽(tīng)器一樣,驗(yàn)證器接受我們傳入所有參數(shù)。
這與prop validation 類似,如果我們的驗(yàn)證器返回 false
,會(huì)在控制臺(tái)得到一個(gè)警告,這為我們提供了一些有用的信息。
MyTextInput.vue
<script setup> const emit = defineEmits({ unvalidatedEvent: null, // if we want an event without validation customChange: (s) => { if (s && typeof s === 'string') { return true } else { console.warn(`Invalid submit event payload!`) return false } }, }) const handleChange = (event) => { // no console warning emit('customChange', event.target.value.toUpperCase()) } onMounted(() => { emit('customChange', 1) // not a string, warning! }) </script>
最佳實(shí)踐
使用 emits 定義自定義事件
如果我們不使用defineEmits
,我們?nèi)匀豢梢酝ㄟ^(guò)export default
中定義emits
選項(xiàng)來(lái)跟蹤一個(gè)組件的自定義事件。
這對(duì)保持良好的組件文檔很重要,如果我們?cè)噲D使用一個(gè)沒(méi)有在 emits 中聲明的事件,也會(huì)從Vue那里得到錯(cuò)誤。
當(dāng)在 emits 選項(xiàng)中定義了原生事件 (如 change) 時(shí),將使用組件中的事件替代原生事件偵聽(tīng)器。
<script> export default { emits: ["change"] // or can pass object with validators } </script> <template> <div> <label>My Custom Input</label> <input type="text" placeholder="Custom input!" @input='$emit("change", $event.target.value)' /> </div> </template>
正確的事件命令
在 vue3 中,與組件和 prop 一樣,事件名提供了自動(dòng)的大小寫(xiě)轉(zhuǎn)換。如果在子組件中觸發(fā)一個(gè)以 camelCase (駝峰式命名) 命名的事件,你將可以在父組件中添加一個(gè) kebab-case (短橫線分隔命名) 的監(jiān)聽(tīng)器。
然而,如果你使用的是Vue 2,事件名稱沒(méi)有自動(dòng)的大小寫(xiě)轉(zhuǎn)換,由于v-on
指令會(huì)自動(dòng)將你的事件名稱轉(zhuǎn)換為小寫(xiě),所以camelCase命名的事件不可能被監(jiān)聽(tīng)到。
例如,如果我們發(fā)出了一個(gè)名為myEvent
的事件,監(jiān)聽(tīng)my-event
將無(wú)法工作。
到此這篇關(guān)于Vue3 $emit用法指南的文章就介紹到這了,更多相關(guān)Vue3 $emit指南內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Win11&Win10配置vue開(kāi)發(fā)環(huán)境詳細(xì)圖文教程
目前前端三大框架(vue、react、angular)中vue是前端工程師經(jīng)常使用的,在使用之前需要搭建vue開(kāi)發(fā)環(huán)境,這篇文章主要給大家介紹了關(guān)于Win11&Win10配置vue開(kāi)發(fā)環(huán)境的相關(guān)資料,需要的朋友可以參考下2024-02-02vue基礎(chǔ)之事件v-onclick="函數(shù)"用法示例
這篇文章主要介紹了vue基礎(chǔ)之事件v-onclick="函數(shù)"用法,結(jié)合實(shí)例形式分析了vue.js事件v-on:click="函數(shù)"的data數(shù)據(jù)添加、點(diǎn)擊響應(yīng)、以及留言本功能相關(guān)操作技巧,需要的朋友可以參考下2019-03-03Vue Object.defineProperty及ProxyVue實(shí)現(xiàn)雙向數(shù)據(jù)綁定
這篇文章主要介紹了Vue Object.defineProperty及ProxyVue實(shí)現(xiàn)雙向數(shù)據(jù)綁定,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-09-09react+?ts?vite搭建及二次封裝請(qǐng)求的過(guò)程解析
這篇文章主要介紹了react+?ts?vite搭建及二次封裝請(qǐng)求,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-04-04vue.js基于v-for實(shí)現(xiàn)批量渲染 Json數(shù)組對(duì)象列表數(shù)據(jù)示例
這篇文章主要介紹了vue.js基于v-for實(shí)現(xiàn)批量渲染 Json數(shù)組對(duì)象列表數(shù)據(jù),結(jié)合實(shí)例形式分析了vue.js使用v-for遍歷json格式數(shù)據(jù)渲染列表相關(guān)操作技巧,需要的朋友可以參考下2019-08-08vue3.0中的雙向數(shù)據(jù)綁定方法及優(yōu)缺點(diǎn)
這篇文章主要介紹了vue3.0中的雙向數(shù)據(jù)綁定方法 ,文中通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-08-08vue實(shí)現(xiàn)excel表格的導(dǎo)入導(dǎo)出的示例
本文主要介紹了vue實(shí)現(xiàn)excel表格的導(dǎo)入導(dǎo)出的示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-04-04