Vue父子組件通訊的四種方法詳解
父子組件通訊
父子組件通訊是指在前端開(kāi)發(fā)的組件化架構(gòu)中,父組件與子組件之間互相傳遞數(shù)據(jù)和觸發(fā)功能的一種機(jī)制。這種機(jī)制使得組件能夠保持獨(dú)立性的同時(shí),也能協(xié)同工作,完成復(fù)雜的界面邏輯和數(shù)據(jù)交互。
通過(guò)一個(gè)用vue實(shí)現(xiàn)的demo為例:
在這個(gè)demo中:
- 需要使用
v-model
指令將文本框內(nèi)的內(nèi)容與變量進(jìn)行雙向綁定,用于獲取文本框內(nèi)的內(nèi)容。 - 通過(guò)一個(gè)數(shù)組存儲(chǔ)需要展示的內(nèi)容,并且使用
v-for
遍歷數(shù)組內(nèi)的內(nèi)容然后渲染。 - 通過(guò)
@click='add'
為按鈕添加一個(gè)點(diǎn)擊事件將文本框的輸入內(nèi)容添加到數(shù)組上。
//組件一 <div class="input-group"> <input type="text" v-model="item"> <button @click="add">添加</button> </div> //組件二(需要數(shù)據(jù)) <div class="child"> <ul> <li v-for="item in list">{{ item }}</li> </ul> </div>
如果我們將組件一放在父組件內(nèi),將組件二放在子組件,那我們要怎么將父組件中數(shù)據(jù)傳遞給子組件進(jìn)行渲染呢?(組件二需要數(shù)據(jù))
這個(gè)時(shí)候就需要進(jìn)行父子組件的通訊。
父向子通訊
父組件向子組件傳遞信息非常方便,通過(guò)子組件的屬性傳遞數(shù)據(jù)就好了。
組件一放在父組件,組件二放在子組件中。父組件將值v-bind
綁定傳給子組件,子組件使用defineProps
接受。
父組件:在<Child :toChild="toChild"></Child>
中用v-bind綁定toChild
變量傳遞給子組件。
<template> <div class="input-group"> <input type="text" v-model="item"> <button @click="add">添加</button> </div> //將數(shù)據(jù)傳遞給子組件 <Child :toChild="toChild"></Child> </template> <script setup> import Child from '@/components/child1.vue' import { ref } from "vue"; const item = ref('') const toChild = ref('') const add = () => { toChild.value = item.value item.value = '' } </script>
子組件:子組件用defineProps
接受父組件傳遞的數(shù)據(jù)并且通過(guò)設(shè)置一個(gè)watch
監(jiān)聽(tīng)器,當(dāng)父組件通過(guò)toChild
屬性傳遞一個(gè)新的值,這個(gè)值就會(huì)被添加到子組件的列表中。
<template> <div class="child"> <ul> <li v-for="item in list">{{ item }}</li> </ul> </div> </template> <script setup> import { defineProps } from 'vue' import { reactive, watch } from "vue"; const list = reactive(['html', 'css', 'javascript']) //接收父組件的數(shù)據(jù) const props = defineProps({ toChild: '' }) //監(jiān)聽(tīng)數(shù)據(jù)的改變動(dòng)態(tài)添加到數(shù)組里 watch(() => props.toChild, (newVal, oldVal) => { list.push(newVal) }) </script>
子向父通訊
子組件向父組件傳遞數(shù)據(jù)較為麻煩一點(diǎn),常見(jiàn)的方法是通過(guò)自定義事件實(shí)現(xiàn)數(shù)據(jù)的傳遞。
將組件二放在父組件,將組件一放在子組件里。
方法一
借助發(fā)布訂閱機(jī)制,子組件負(fù)責(zé)發(fā)布事件攜帶參數(shù),父組件訂閱該事件通過(guò)事件參數(shù)獲取子組件提供的值。
子組件:通過(guò)defineEmits
定義并創(chuàng)建一個(gè)add
事件,再通過(guò)觸發(fā)點(diǎn)擊事件的處理函數(shù)用emits
發(fā)布add
事件,并且攜帶數(shù)據(jù)。
<template> <div class="input-group"> <input type="text" v-model="item"> <button @click="add">添加</button> </div> </template> <script setup> import { ref } from "vue"; const item = ref('') const emits = defineEmits(['add'])//創(chuàng)建一個(gè)add事件 const add = () => { //將item變量給到父組件 emits('add', item.value)//發(fā)布add事件 item.value = '' } </script>
父組件:通過(guò)<child @add="handle"></child>
給子組件綁定自定義的add
事件并且以handle
函數(shù)作為處理函數(shù)。當(dāng)add
事件發(fā)布時(shí),就會(huì)觸發(fā)執(zhí)行handle
函數(shù)并且通過(guò)handle
函數(shù)的參數(shù)接收子組件傳遞的數(shù)據(jù)。
<template> <!-- 訂閱add事件,子組件什么時(shí)候發(fā)布add事件,父組件就會(huì)執(zhí)行handle函數(shù),從而實(shí)現(xiàn)數(shù)據(jù)的共享 --> <child @add="handle"></child> <div class="child"> <ul> <li v-for="item in list">{{ item }}</li> </ul> </div> </template> <script setup> import child from '@/components/child2.vue' import { reactive } from "vue"; const list = reactive(['html', 'css', 'javascript']) const handle = (value) => { list.push(value) } </script>
這種方法中子組件只需要發(fā)布自定義事件并且攜帶數(shù)據(jù),父組件只需要監(jiān)聽(tīng)自定義事件并且接受數(shù)據(jù)。
方法二
父組件借助v-model
將數(shù)據(jù)綁定給子組件,子組件創(chuàng)建update:xxx
事件,并接收到該數(shù)據(jù)將修改后的數(shù)據(jù)emits(發(fā)布)出來(lái)讓父組件接收修改后的數(shù)據(jù)。
父組件:在<child v-model:list="list"></child>
中,使用v-model:list
將父組件中的 list
數(shù)據(jù)(渲染數(shù)組)傳遞給子組件并且進(jìn)行綁定,當(dāng)子組件發(fā)布 update:list
事件后,父組件將接收到修改后的渲染數(shù)組并且進(jìn)行重新渲染。
<template> <div> <child v-model:list="list"></child> <div class="child"> <ul> <li v-for="item in list">{{ item }}</li> </ul> </div> </div> </template> <script setup> import child from '@/components/child3.vue' import {reactive } from "vue"; const list = reactive(['html', 'css', 'javascript']) </script>
子組件:子組件通過(guò)defineProps
接收父組件發(fā)送的list
,并且自定義一個(gè)Update:list
事件。當(dāng)點(diǎn)擊按鈕后觸發(fā)add
函數(shù),將文本框數(shù)據(jù)放入list
中,然后發(fā)布Update:list
事件并且攜帶著修改后的list
。隨著Update:list
事件的發(fā)布,父組件就可以接收到修改后的list
。
<template> <div> <div class="input-group"> <input type="text" v-model="item"> <button @click="add">添加</button> </div> </div> </template> <script setup> import { ref } from "vue"; const item = ref('') const props = defineProps({ list: { type: Array, default: () => [] } }) const emits = defineEmits(['Update:list']) const add = () => { const arr = props.list arr.push(item.value) emits('Update:list', arr) item.value = '' } </script>
這種方法使父組件的操作變得簡(jiǎn)潔,但將子組件的操作變得復(fù)雜了。父組件只需要和子組件進(jìn)行雙向綁定數(shù)據(jù)就行了,子組件則需要接收數(shù)據(jù)再發(fā)布自定義的Update:xxx
事件將修改后的數(shù)據(jù)傳遞給父組件。
方法三
父組件通過(guò)ref
獲取子組件中defineExprose()
暴露出來(lái)的數(shù)據(jù)。
子組件:使用 defineExpose
暴露數(shù)據(jù),子組件通過(guò)defineExpose({ list })
將更新后的渲染數(shù)組暴露給父組件。
<template> <div class="input-group"> <input type="text" v-model="item"> <button @click="add">添加</button> </div> </template> <script setup> import { ref, reactive } from "vue"; const item = ref('') const list = reactive(['html', 'css', 'javascript']) const add = () => { list.push(item.value) item.value = '' } defineExpose({ list }) </script>
父組件:獲取子組件的數(shù)據(jù),使用 ref
定義一個(gè)引用變量來(lái)引用子組件,并在適當(dāng)?shù)臅r(shí)機(jī)獲取子組件暴露的渲染數(shù)組。將子組件暴露的渲染數(shù)組作為v-for
的循環(huán)對(duì)象進(jìn)行渲染。
<template> //獲取子組件的引用 <child ref="childRef"></child> <div class="child"> <ul> //childRef?.list表示只有在在子組件已經(jīng)掛載完成后才能訪問(wèn)子組件暴露的list數(shù)據(jù) <li v-for="item in childRef?.list">{{ item }}</li> </ul> </div> </template> <script setup> import child from '@/components/child4.vue' import { ref, reactive, onMounted } from "vue"; //用ref定義一個(gè)引用變量 const childRef = ref(null); </script>
這種方法十分簡(jiǎn)便,子組件只需要暴露數(shù)據(jù)給父組件,然后父組件引用子組件暴露的數(shù)據(jù),但是需要注意生命周期,需要在組件掛載完成后父組件才能成功獲取子組件的數(shù)據(jù)。
以上就是Vue父子組件通訊的四種方法詳解的詳細(xì)內(nèi)容,更多關(guān)于Vue父子組件通訊的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Vue?響應(yīng)式系統(tǒng)依賴收集過(guò)程原理解析
Vue 初始化時(shí)就會(huì)通過(guò) Object.defineProperty 攔截屬性的 getter 和 setter ,為對(duì)象的每個(gè)值創(chuàng)建一個(gè) dep 并用 Dep.addSub() 來(lái)存儲(chǔ)該屬性值的 watcher 列表,這篇文章主要介紹了Vue?響應(yīng)式系統(tǒng)依賴收集過(guò)程分析,需要的朋友可以參考下2022-06-06element?table?數(shù)據(jù)量大頁(yè)面卡頓的解決
這篇文章主要介紹了element?table?數(shù)據(jù)量大頁(yè)面卡頓的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-01-01vue+element+Java實(shí)現(xiàn)批量刪除功能
這篇文章主要介紹了vue+element+Java實(shí)現(xiàn)批量刪除功能,代碼簡(jiǎn)單易懂,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-04-04vue-cli4創(chuàng)建項(xiàng)目導(dǎo)入Element-UI踩過(guò)的坑及解決
這篇文章主要介紹了vue-cli4創(chuàng)建項(xiàng)目導(dǎo)入Element-UI踩過(guò)的坑及解決,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-04-04