Vue3中父子組件之間相互通信的方式詳解
前言
父子組件通信,作為Vue應(yīng)用開發(fā)中不可或缺的一部分,是實(shí)現(xiàn)數(shù)據(jù)流動(dòng)、事件觸發(fā)以及組件間互動(dòng)的關(guān)鍵機(jī)制。無論是簡單的屬性傳遞,還是復(fù)雜的交互邏輯,掌握這一技能對(duì)于構(gòu)建富有層次感和互動(dòng)性的用戶界面至關(guān)重要。通過學(xué)習(xí)如何有效地利用props
進(jìn)行數(shù)據(jù)下行傳遞,使用emit
觸發(fā)自定義事件,以及借助ref
直接操作子組件。本文將詳細(xì)探討Vue 3中的父子組件通信,幫助你深入了解并掌握這些核心概念。
父傳子
使用Props傳遞數(shù)據(jù)和方法
在Vue中,父組件向子組件傳遞數(shù)據(jù)最常用的方法是通過props
。props
允許父組件以一種聲明式的方式向下傳遞數(shù)據(jù)到子組件。這種方式不僅簡化了數(shù)據(jù)流的管理,還確保了組件之間的單向數(shù)據(jù)綁定,使得狀態(tài)更易于追蹤和調(diào)試。
代碼模塊
App.vue
<script setup> import ChildComponent from './components/ChildComponent.vue' import { ref } from 'vue' const title=ref("來自父組件的消息") const method =()=>{ console.log("來自父組件的方法") } </script> <template> <div> <h2>父組件</h2> <ChildComponent :title="title" :parentmethod="method" /> </div> </template> <style scoped> </style>
解析:
const title
:創(chuàng)建了一個(gè)響應(yīng)式的引用(ref
),它的值是“來自父組件的消息”。這個(gè)引用可以被傳遞給子組件,并且如果在父組件中修改了它的值,子組件會(huì)自動(dòng)更新。const method
:定義了一個(gè)簡單的方法,當(dāng)它被執(zhí)行時(shí),會(huì)在瀏覽器的控制臺(tái)輸出一條信息。:title="title"
的意思就是:將父組件中的title
響應(yīng)式變量的值綁定到子組件的title
prop上。每當(dāng)父組件中的title
發(fā)生變化時(shí),子組件也會(huì)自動(dòng)更新其對(duì)應(yīng)的title
prop,并反映出最新的值。:parentmethod="method"
同理
ChildComponent.vue
<template> <div> 在子組件中: {{props.title}} <button @click="props.parentmethod">子組件調(diào)用父組件的方法</button> </div> </template> <script setup> import { defineProps, ref } from 'vue' const props=defineProps({ title:{ type:String, required:true }, parentmethod:{ type:Function, required:true } }) </script> <style scoped> </style>
- 接收
props
:子組件通過defineProps
聲明了它期望從父組件接收兩個(gè)props
:title
和parentmethod
。根據(jù)填寫required
的true|flase
,是否判斷必需傳入。這兩個(gè)props
都是必需的,并且有type來定義明確的類型。 - 顯示
props
:在模板中,子組件使用{{ props.title }}
來顯示父組件傳遞過來的標(biāo)題。 - 調(diào)用父組件方法:子組件還包含了一個(gè)按鈕,其點(diǎn)擊事件被綁定到了
props.parentmethod
。這意味著當(dāng)用戶點(diǎn)擊按鈕時(shí),子組件會(huì)觸發(fā)父組件中定義的方法。由于parentmethod
是從父組件傳入的一個(gè)函數(shù)引用,因此它會(huì)在父組件的作用域內(nèi)執(zhí)行。 - 響應(yīng)性:因?yàn)?code>title是一個(gè)響應(yīng)式的
prop
,如果父組件更新了它的值,子組件也會(huì)自動(dòng)重新渲染以反映最新的標(biāo)題。
效果:
子傳父
使用Emit觸發(fā)自定義事件
子組件與父組件通信的主要方式之一是通過emit
觸發(fā)自定義事件。當(dāng)子組件想要通知父組件某個(gè)特定事件發(fā)生時(shí),它可以調(diào)用emit
來觸發(fā)一個(gè)命名事件,并可以選擇性地傳遞額外的數(shù)據(jù)。 App.vue
<script setup> import ChildComponent from './components/ChildComponent.vue' import { ref } from 'vue' const title=ref("來自父組件的消息") const method =()=>{ console.log("來自父組件的方法") } const messageFromChild=ref("") const handleChildMessage = (message) => { console.log('來自子組件的消息:', message); messageFromChild.value=message // 在這里可以處理子組件發(fā)送的消息 }; </script> <template> <div> <h2>父組件</h2> <ChildComponent :title="title" :parentmethod="method" @child-message="handleChildMessage"/> <p>來自子組件的消息:{{messageFromChild}}</p> </div> </template> <style scoped> </style>
@child-message="handleEvent"
自定義事件名稱 attrs + 處理函數(shù)child-message
:這是你為子組件定義的一個(gè)自定義事件名稱。它不是內(nèi)置的DOM事件(如click
、input
等),而是由開發(fā)者根據(jù)需求命名的。通過這個(gè)名稱,子組件可以觸發(fā)特定事件并向父組件傳遞數(shù)據(jù)。handleEvent
:這是父組件中定義的一個(gè)方法,用來處理來自子組件的消息。當(dāng)你在父組件模板中使用@child-message="handleEvent"
時(shí),實(shí)際上是在說:“每當(dāng)子組件觸發(fā)child-message
事件時(shí),請調(diào)用handleEvent
方法”。
ChildComponent.vue
<template> <div> 在子組件中: {{props.title}} <hr> <button @click="props.parentmethod">子組件調(diào)用父組件的方法</button> <hr> <button @click="childMessage">子組件給父組件發(fā)送數(shù)據(jù)</button> </div> </template> <script setup> import { defineProps, ref, defineEmits, } from 'vue' const props=defineProps({ title:{ type:String, required:true }, parentmethod:{ type:Function, required:true } }) const emit = defineEmits(['child-message']) const childMessage = () => { emit('child-message', '我是子組件'); }; </script> <style scoped> </style>
解析:
const emit = defineEmits(['child-message'])
defineEmits
:這是Vue Composition API的一部分,用于定義子組件可以觸發(fā)的自定義事件列表。它返回一個(gè)函數(shù)emit
,該函數(shù)可以用來觸發(fā)這些事件。['child-message']
:這里是一個(gè)字符串?dāng)?shù)組,列出了所有可以由子組件觸發(fā)的自定義事件名稱。在這個(gè)例子中,我們只定義了一個(gè)名為child-message
的事件,如果有多個(gè)事件,可以通過數(shù)組的形式添加。
const childMessage....
emit('child-message', '我是子組件')
:調(diào)用emit
函數(shù)來觸發(fā)一個(gè)名為child-message
的自定義事件,并傳遞一個(gè)字符串'我是子組件'
作為參數(shù)。這個(gè)消息會(huì)被發(fā)送給監(jiān)聽了child-message
事件的父組件。
效果:
圖解:
當(dāng)我們實(shí)現(xiàn)完子組件向父組件,傳遞信息后,那么長的帥的讀者就要問了?怎么向父組件傳遞方法呢?
使用ref實(shí)現(xiàn)子組件對(duì)父組件的傳遞
創(chuàng)建響應(yīng)式引用:
大家都知道ref
可以用來創(chuàng)建一個(gè)響應(yīng)式的變量,該變量可以被綁定到模板中的元素或組件上。當(dāng)這個(gè)變量的值發(fā)生變化時(shí),視圖會(huì)自動(dòng)更新。
import { ref } from 'vue' const count = ref(0)
訪問子組件實(shí)例:
當(dāng)你需要直接與子組件進(jìn)行交互時(shí)(比如調(diào)用子組件的方法或訪問它的屬性),可以通過給子組件添加 ref
屬性來獲取子組件的實(shí)例。
代碼:
我們可以先看子組件向父組件輸出了什么? parent組件:
<template> <div> <Child ref="comp" /> <button @click="handlerClick">按鈕</button> </div> </template> <script setup> import { ref } from 'vue' import Child from './Child.vue' const comp = ref(null) // 標(biāo)記DOM 元素 null 組件沒用掛載,DOM 也不在 const title = ref('hello') // 標(biāo)記數(shù)據(jù) const handlerClick = ()=>{ console.log(comp,comp.value) console.log( comp.value.childName) comp.value.someMethod() } </script> <style scoped> </style>
child組件:
<template> <div> Child </div> </template> <script setup> import { defineProps, defineEmits, defineExpose, ref } from 'vue' defineExpose({ childName:"這是子組件的屬性", someMethod:()=>{ console.log('這是子組件的方法') } }) </script> <style scoped> </style>
解析:
重點(diǎn):
<Child ref="comp" />
:這里定義了一個(gè)子組件Child
,并通過ref
屬性給它指定了一個(gè)名為comp
的引用。這使得父組件可以在JavaScript中直接訪問這個(gè)子組件實(shí)例,調(diào)用子組件的方法和屬性。defineExpose({ ... })
:這是Vue Composition API的一部分,用來明確哪些屬性或方法應(yīng)該暴露給父組件。在這個(gè)例子中,我們暴露了兩個(gè)成員:childName
:一個(gè)字符串,作為子組件的一個(gè)公開屬性。someMethod
:一個(gè)函數(shù),作為子組件的一個(gè)公開方法,可以被父組件調(diào)用。
最后在父組件就可以通過
comp.value.
,調(diào)用方法或者屬性。
運(yùn)行機(jī)制
掛載階段:當(dāng)父組件首次渲染時(shí),子組件也會(huì)一同被掛載。此時(shí),
comp.value
會(huì)被更新為指向子組件的實(shí)例。點(diǎn)擊按鈕:用戶點(diǎn)擊按鈕后,
handlerClick
函數(shù)被執(zhí)行。由于此時(shí)子組件已經(jīng)掛載完成,因此可以通過comp.value
訪問到子組件實(shí)例,并且可以安全地調(diào)用它的公開屬性和方法。輸出結(jié)果:
- 控制臺(tái)首先會(huì)打印出
comp
引用及其當(dāng)前值(即子組件實(shí)例)。 - 接著會(huì)打印出子組件的
childName
屬性值:“這是子組件的屬性”。 - 最后,調(diào)用子組件的
someMethod
方法,在控制臺(tái)上輸出:“這是子組件的方法”。
- 控制臺(tái)首先會(huì)打印出
效果:
總結(jié):
- 父傳子 - 使用
props
傳遞數(shù)據(jù)和方法:父組件可以通過props
將數(shù)據(jù)和方法傳遞給子組件,這種方式不僅簡化了數(shù)據(jù)流的管理,還確保了組件之間的單向數(shù)據(jù)綁定,使得狀態(tài)更易于追蹤和調(diào)試。 - 子傳父 - 使用
emit
觸發(fā)自定義事件:子組件可以通過emit
觸發(fā)自定義事件來通知父組件某些特定事件的發(fā)生,并可以選擇性地傳遞額外的數(shù)據(jù)。父組件可以通過監(jiān)聽這些事件來做出相應(yīng)的反應(yīng)。 - 使用
ref
直接操作子組件實(shí)例:當(dāng)需要直接與子組件進(jìn)行交互時(shí),比如調(diào)用子組件的方法或訪問它的屬性,可以通過給子組件添加ref
屬性來獲取子組件的實(shí)例。借助defineExpose
,可以有選擇性地暴露子組件的屬性和方法給父組件。
以上就是Vue3中父子組件之間相互通信的方式詳解的詳細(xì)內(nèi)容,更多關(guān)于Vue3父子組件通信方式的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
基于 flexible 的 Vue 組件:Toast -- 顯示框效果
這篇文章主要介紹了基于 flexible 的 Vue 組件:Toast -- 顯示框效果,需要的朋友可以參考下2017-12-12Vue.js實(shí)現(xiàn)網(wǎng)格列表布局轉(zhuǎn)換方法
下面小編就為大家?guī)硪黄猇ue.js實(shí)現(xiàn)網(wǎng)格列表布局轉(zhuǎn)換方法。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-08-08vue+element+Java實(shí)現(xiàn)批量刪除功能
這篇文章主要介紹了vue+element+Java實(shí)現(xiàn)批量刪除功能,代碼簡單易懂,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-04-04Vue如何使用Element-ui表單發(fā)送數(shù)據(jù)與多張圖片到后端詳解
在做項(xiàng)目的時(shí)候遇到一個(gè)問題,前端需要上傳表單到后端,表單數(shù)據(jù)包括文本內(nèi)容和圖片,這篇文章主要給大家介紹了關(guān)于Vue如何使用Element-ui表單發(fā)送數(shù)據(jù)與多張圖片到后端的相關(guān)資料,需要的朋友可以參考下2022-04-04