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