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