Vue3中的常見組件通信之props和自定義事件詳解
Vue3中的常見組件通信
概述
在vue3中常見的組件通信有props、mitt、v-model、 refs、parent、provide、inject、pinia、slot等。不同的組件關(guān)系用不同的傳遞方式。常見的撘配形式如下表所示。
組件關(guān)系 | 傳遞方式 |
---|---|
父?jìng)髯?/td> | 1. props2. v-model3. $refs4. 默認(rèn)插槽、具名插槽 |
子傳父 | 1. props2. 自定義事件3. v-model4. $parent5. 作用域插槽 |
祖?zhèn)鲗O、孫傳祖 | 1. $attrs2. provide、inject |
兄弟間、任意組件間 | 1. mitt2. pinia |
本文講述props和自定義事件,其他的通信方式后面再更新。
1.props
1.1 準(zhǔn)備父子組件
首先準(zhǔn)備一個(gè)簡(jiǎn)單的父子組件的樣式,如下是父組件代碼:
<template> <div class="father"> <h2>這是父組件</h2> <Child/> </div> </template> <script setup lang="ts" name="Father"> //引入子組件 import Child from './Child.vue'; </script> <style scoped> .father{ margin: 5px; background-color:rgb(205, 165, 32); padding: 20px; color: white; } </style>
以下是子組件代碼:
<template> <div class="child"> <h2>這是子組件</h2> </div> </template> <script setup lang="ts" name="Child"> </script> <style scoped> .child{ margin: 5px; background-color: rgba(93, 135, 20, 0.224); border: 1px solid; border-color: white; box-shadow: 0 0 5px; padding: 10px; color: #000; } </style>
運(yùn)行結(jié)果如下所示:
1.2 父?jìng)髯油ㄐ诺膶?shí)現(xiàn)
用props實(shí)現(xiàn)父?jìng)髯油ㄐ?,可以用?biāo)簽中的屬性值直接傳遞數(shù)據(jù),父組件代碼中只需要在子組件標(biāo)簽上添加屬性值即可,如下代碼,傳遞兩個(gè)數(shù)據(jù):
<Child :f2CMsg="f2CMsg" :f2CObj="f2CObj"/>
定義傳遞的數(shù)據(jù)內(nèi)容,兩個(gè)數(shù)據(jù)分別是ref定義的基本類型的響應(yīng)式數(shù)據(jù)和reactive定義的對(duì)象類型的響應(yīng)式數(shù)據(jù)。
//引入ref和reactive import {ref,reactive} from 'vue' //數(shù)據(jù),ref定義的基本類型的響應(yīng)式數(shù)據(jù) let f2CMsg =ref('你好,子組件。') //數(shù)據(jù),reactive定義的對(duì)象類型的響應(yīng)式數(shù)據(jù) let f2CObj = reactive({ id:"asdfg01", name:"張三", age:18, detail:"這是父組件中的對(duì)象信息" })
在子組件中需要聲明接收數(shù)據(jù)props,注意接收的數(shù)據(jù)格式是數(shù)組,哪怕是只傳遞一個(gè)數(shù)據(jù)也要寫成數(shù)組的形式。
//聲明接收數(shù)據(jù)props defineProps(['f2CMsg','f2CObj'])
子組件中在頁(yè)面展示接收的數(shù)據(jù),如下代碼:
<h4>父組件傳遞的信息:{{ f2CMsg }}</h4> <h4>父組件傳遞的對(duì)象:</h4> <ul> <li>姓名:{{f2CObj.name}}</li> <li>年齡:{{f2CObj.age}}</li> <li>詳情:{{f2CObj.detail}}</li> </ul>
然后運(yùn)行結(jié)果如下:
1.3 子傳父通信的實(shí)現(xiàn)
用props實(shí)現(xiàn)子傳父的通信需要父組件先向子組件傳遞一個(gè)函數(shù),然后傳遞的數(shù)據(jù)以參數(shù)的形式傳遞給函數(shù),父組件中先定義子傳父的數(shù)據(jù)變量和函數(shù)或者方法如下:
//定義子傳父的數(shù)據(jù)變量 let c2FMsg = ref('') //定義方法傳遞給子組件 function getMsg(value:string){ c2FMsg.value = value }
在標(biāo)簽中把方法傳給子組件:
<Child :f2CMsg="f2CMsg" :f2CObj="f2CObj" :sendMsg="getMsg"/>
在子組件中接收數(shù)據(jù),并定義數(shù)據(jù)內(nèi)容:
defineProps(['f2CMsg','f2CObj','sendMsg']) let c2FMsg = ref('你好,父組件。')
在子組件中設(shè)置一個(gè)按鈕,給按鈕綁定點(diǎn)擊事件,點(diǎn)擊事件觸發(fā)sendMsg方法,并傳遞參數(shù):
<button @click="sendMsg(c2FMsg)">點(diǎn)我向父組件傳遞信息</button>
現(xiàn)在數(shù)據(jù)應(yīng)該已經(jīng)傳遞給了父組件,在父組件可以用如下代碼展示:
<h4 v-show="c2FMsg">子組件傳遞的信息:{{ c2FMsg }}</h4>
運(yùn)行結(jié)果如下:
點(diǎn)擊按鈕后運(yùn)行結(jié)果如下:
至此我們已經(jīng)用props實(shí)現(xiàn)了子傳父的通信功能。當(dāng)然子傳父也可以傳遞對(duì)象。此處不再展示。如下是完整代碼:
父組件中的代碼:
<template> <div class="father"> <h2>這是父組件</h2> <h4 v-show="c2FMsg">子組件傳遞的信息:{{ c2FMsg }}</h4> <Child :f2CMsg="f2CMsg" :f2CObj="f2CObj" :sendMsg="getMsg"/> </div> </template> <script setup lang="ts" name="Father"> //引入子組件 import Child from './Child.vue'; //引入ref和reactive import {ref,reactive} from 'vue' //數(shù)據(jù),ref定義的基本類型的響應(yīng)式數(shù)據(jù) let f2CMsg =ref('你好,子組件。') //數(shù)據(jù),reactive定義的對(duì)象類型的響應(yīng)式數(shù)據(jù) let f2CObj = reactive({ id:"asdfg01", name:"張三", age:18, detail:"這是父組件中的對(duì)象信息" }) //定義子傳父的數(shù)據(jù)變量 let c2FMsg = ref('') //定義方法傳遞給子組件 function getMsg(value:string){ c2FMsg.value = value } </script> <style scoped> .father{ margin: 5px; background-color:rgb(205, 165, 32); padding: 20px; color: white; } </style>
子組件的代碼:
<template> <div class="child"> <h2>這是子組件</h2> <h4>父組件傳遞的信息:{{ f2CMsg }}</h4> <h4>父組件傳遞的對(duì)象:</h4> <ul> <li>姓名:{{f2CObj.name}}</li> <li>年齡:{{f2CObj.age}}</li> <li>詳情:{{f2CObj.detail}}</li> </ul> <button @click="sendMsg(c2FMsg )">點(diǎn)我向父組件傳遞信息</button> </div> </template> <script setup lang="ts" name="Child"> import { ref,reactive } from 'vue'; //聲明接收數(shù)據(jù)props defineProps(['f2CMsg','f2CObj','sendMsg']) let c2FMsg = ref('你好,父組件。') </script> <style scoped> .child{ margin: 5px; background-color: rgba(93, 135, 20, 0.224); border: 1px solid; border-color: white; box-shadow: 0 0 5px; padding: 10px; color: #000; } </style>
1.4 小結(jié)
用props實(shí)現(xiàn)父子通信的步驟是這樣的:
- 父?jìng)髯樱焊附M件中定義傳遞的數(shù)據(jù)–>標(biāo)簽中用屬性值直接傳遞數(shù)據(jù)–>子組件中聲明接收數(shù)據(jù)–>用插值語(yǔ)法展示數(shù)據(jù)。
- 子傳父: 父組件先定義接收數(shù)據(jù)的變量–>父組件中定義函數(shù)–>將函數(shù)傳遞給子組件–>子組件中聲明接收數(shù)據(jù),接收的數(shù)據(jù)為函數(shù)–>子組件中定義傳遞的數(shù)據(jù)–>子組件中調(diào)用接收的函數(shù),將定義的要傳遞的數(shù)據(jù)作為參數(shù)進(jìn)行傳遞–>父組件中收到數(shù)據(jù),可以在頁(yè)面中展示。
最后總結(jié)如下:
- 父?jìng)髯?/strong>:標(biāo)簽中的屬性值是非函數(shù)
- 子傳父:標(biāo)簽中的屬性值是函數(shù)
2. 自定義事件
- 自定義事件通常用于子傳父,需要注意在原生事件中事件名是特定的,比如click,keyup等,在自定義事件中事件名是任意的;
- 在原生事件中事件對(duì)象event是包含事件相關(guān)信息的對(duì)象(‘pageX‘、‘pageY‘、‘target‘、‘keyCode‘)
- 在定義事件中事件對(duì)象event是調(diào)用emit所提供的數(shù)據(jù),可以是任意類型。
2.1 準(zhǔn)備父子組件
父子組件代碼與樣式與本文中1.1中的完全相同,此處不再贅述。
2.2 自定義事件實(shí)現(xiàn)子傳父通信
首先在子組件中定義要傳遞的數(shù)據(jù),此次依然已字符串為例,如下代碼:
let c2FMsg = ref('你好,父組件。')
然后在父組件中定義接收的數(shù)據(jù)變量,并聲明函數(shù),用來(lái)保存接收的數(shù)據(jù)。
let c2FMsg = ref('') //聲明函數(shù)saveMsg,用來(lái)保存接收的數(shù)據(jù) function saveMsg(value:string){ c2FMsg.value = value }
之后給子組件綁定自定義事件,事件名為send-message,同時(shí)將函數(shù)saveMsg傳進(jìn)去,注意自定義事件名的命名規(guī)范官方建議采用肉串形式的命名方式。
<!-- 給子組件綁定自定義事件 --> <Child @send-message="saveMsg"/>
在子組件中需要聲明事件
//聲明事件 let emit = defineEmits(['send-message'])
觸發(fā)事件的代碼如下:
emit('send-message')
只要在子組件中寫出上面觸發(fā)事件的代碼,就可以實(shí)現(xiàn)子傳父的通信,這次以子組件掛載3秒后自動(dòng)觸發(fā)事件為例,如下代碼:
//組件掛載3秒后觸發(fā)事件 onMounted(()=>{ setTimeout(()=>{ //觸發(fā)事件send-message,并傳c2FMsg emit('send-message',c2FMsg) },3000) })
此時(shí)已經(jīng)實(shí)現(xiàn)了子傳父的通信,最后在父組件中展示出來(lái),如下代碼:
<h3 v-show="c2FMsg">子組件傳遞的信息:{{ c2FMsg }}</h3>
最后運(yùn)行頁(yè)面效果如下,在剛啟動(dòng)頁(yè)面是如下效果:
3秒鐘之后看下的效果如下圖所示:
以下是完整代碼:
父組件代碼:
<template> <div class="father"> <h2>這是父組件</h2> <h3 v-show="c2FMsg">子組件傳遞的信息:{{ c2FMsg }}</h3> <!-- 給子組件綁定自定義事件 --> <Child @send-message="saveMsg"/> </div> </template> <script setup lang="ts" name="Father"> //引入子組件 import Child from './Child.vue'; import { ref } from 'vue'; let c2FMsg = ref('') //聲明函數(shù),用來(lái)保存接收的數(shù)據(jù) function saveMsg(value:string){ c2FMsg.value = value } </script> <style scoped> .father{ margin: 5px; background-color:rgb(205, 165, 32); padding: 20px; color: white; } </style>
以下是子組件代碼:
<template> <div class="child"> <h2>這是子組件</h2> </div> </template> <script setup lang="ts" name="Child"> import {ref,onMounted} from 'vue' let c2FMsg = ref('你好,父組件。') //聲明事件 let emit = defineEmits(['send-message']) //組件掛載3秒后觸發(fā)事件 onMounted(()=>{ setTimeout(()=>{ //觸發(fā)事件send-message,并傳c2FMsg emit('send-message',c2FMsg) },3000) }) </script> <style scoped> .child{ margin: 5px; background-color: rgba(93, 135, 20, 0.224); border: 1px solid; border-color: white; box-shadow: 0 0 5px; padding: 10px; color: #000; } </style>
總結(jié)
以上便是自定義事件的基本用法,在實(shí)際開發(fā)中是比較常用的用來(lái)實(shí)現(xiàn)子傳父的通信方式。
這些僅為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Vue向后臺(tái)傳數(shù)組數(shù)據(jù),springboot接收vue傳的數(shù)組數(shù)據(jù)實(shí)例
這篇文章主要介紹了Vue向后臺(tái)傳數(shù)組數(shù)據(jù),springboot接收vue傳的數(shù)組數(shù)據(jù)實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來(lái)看看吧2020-11-11el-upload大文件切片上傳實(shí)現(xiàn)示例詳解
這篇文章主要為大家介紹了el-upload大文件切片上傳實(shí)現(xiàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-03-03Vue3?通過作用域插槽實(shí)現(xiàn)樹形菜單嵌套組件
這篇文章主要為大家介紹了Vue3?通過作用域插槽實(shí)現(xiàn)樹形菜單嵌套組件示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-01-01vue+elementUI多表單同時(shí)提交及表單校驗(yàn)最新解決方案
假設(shè)有一個(gè)頁(yè)面,需要分三步填寫三個(gè)表單,且每個(gè)表單位于獨(dú)立的組件中,然后最后保存同時(shí)提交,如何進(jìn)行表單必填項(xiàng)校驗(yàn),下面小編給大家介紹vue+elementUI多表單同時(shí)提交及表單校驗(yàn)最新解決方案,感興趣的朋友一起看看吧2024-03-03Vue3+ElementPlus 表單組件的封裝實(shí)例
這篇文章主要介紹了Vue3+ElementPlus 表單組件的封裝實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-06-06解決webpack+Vue引入iView找不到字體文件的問題
今天小編就為大家分享一篇解決webpack+Vue引入iView找不到字體文件的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來(lái)看看吧2018-09-09vue項(xiàng)目中vue-i18n和element-ui國(guó)際化開發(fā)實(shí)現(xiàn)過程
這篇文章主要介紹了vue項(xiàng)目中vue-i18n和element-ui國(guó)際化開發(fā)實(shí)現(xiàn)過程,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2018-04-04