vue父子組件通訊的所有方法小結(jié)
父子組件通訊
父組件展示輸入框用于新增數(shù)據(jù),子組件展示數(shù)組信息
場景一:直接傳遞一整個數(shù)組
父組件在子組件標(biāo)簽中使用v-bind
綁定一個屬性名為list
,屬性值為要傳遞的數(shù)組list
子組件調(diào)用函數(shù)defineProps
,接收父組件傳過來的數(shù)據(jù)。defineProps
函數(shù)是vue默認(rèn)幫我們引入好了的,它默認(rèn)接收一個對象作為參數(shù),該對象包含一個字段,字段名為父組件綁定的屬性名list
,字段值又為一個對象,對象中包含子組件期望接收到的數(shù)據(jù)類型type
和默認(rèn)值default
,此處期望接收到一個數(shù)組,默認(rèn)值為一個空數(shù)組。list
可以直接拿到template模塊中使用
父組件代碼:
<template> <div class="inputGroup"> <input type="text" v-model="value"> <button @click="add">添加</button> </div> <Child :list="list"> </Child> // 父組件將值v-bind綁定傳給子組件 </template> <script setup> import Child from '@/components/child.vue' // 引入子組件 import { ref } from 'vue' const value = ref('') const list = ref(['html', 'css', 'js']) const add = () => { list.value.push(value.value) value.value = '' } </script>
子組件代碼:
<template> <div class="child"> <ul> <li v-for="item in list">{{ item }}</li> </ul> </div> </template> <script setup> defineProps({ // 子組件使用defineProps接收 list: { type: Array, required: true, default: () => [] } }) </script>
這個通訊過程本身就是一個響應(yīng)式的過程,所以父組件向子組件傳遞過去的屬性值 list 發(fā)生改變后,子組件會重新接收一遍最新的值,由于 list 被定義成了響應(yīng)式,瀏覽器最終就會將新添加的值成功渲染出來
場景二:只傳遞新增加的那個值
父組件在子組件標(biāo)簽中使用v-bind
綁定一個屬性名為msg
,屬性值為要傳遞的新增數(shù)據(jù)toChild
子組件定義一個變量props
接收defineProps
函數(shù)執(zhí)行的結(jié)果,再將接收到的新增數(shù)據(jù) props.msg
添加進(jìn)子組件已經(jīng)定義好的list
數(shù)組中
父組件代碼:
<template> <div class="inputGroup"> <input type="text" v-model="value"> <button @click="add">添加</button> </div> <Child :msg="toChild"> </Child> </template> <script setup> import Child from '@/components/child.vue' // 引入子組件 import { ref } from 'vue' const value = ref('') const toChild = ref('') const add = () => { toChild.value = value.value } </script>
子組件代碼:
<template> <div class="child"> <ul> <li v-for="item in list">{{ item }}</li> </ul> </div> </template> <script setup> import { ref, watch } from 'vue' const list = ref(['html', 'css', 'js']) const props = defineProps({ msg: '' // 直接簡寫,不再把msg對應(yīng)的值寫成一個對象 }) watch( // 監(jiān)視props.msg的值的變化,一旦變化執(zhí)行回調(diào)函數(shù) () => props.msg, (newVal, oldVal) => { list.value.push(newVal) } ) </script>
defineProps
函數(shù)中的字段可以直接被拿到template中使用,但如果要在js腳本中使用,需要一個變量來接收這個函數(shù)的執(zhí)行結(jié)果
注意:這里不直接
list.value.push(props.msg)
,而是需要watch
對props.msg
的值進(jìn)行監(jiān)聽是因為:list的更新需要list.value.push()
這句js代碼反復(fù)去執(zhí)行,而js代碼在瀏覽器第一遍渲染頁面完成后,不會再執(zhí)行第二遍,所以需要watch函數(shù)在監(jiān)視到值變化后,主動去執(zhí)行l(wèi)ist的更新
子父組件通訊一
父組件展示數(shù)組信息,子組件展示輸入框用于新增數(shù)據(jù)
借助發(fā)布訂閱機(jī)制,子組件調(diào)用defineEmits
函數(shù)接受一個數(shù)組作為參數(shù),數(shù)組 [ 'new' ]
表示組件可以觸發(fā)一個名為 'new'
的自定義事件,返回給emits
對象,可以用它來觸發(fā) new
事件。點擊按鈕后,調(diào)用emits
函數(shù)發(fā)布事件,傳遞的參數(shù)分別為要傳輸給父組件的事件名new
和事件值value.value
父組件訂閱該事件,通過事件參數(shù)獲取子組件提供的值
父組件代碼:
<template> <!-- 訂閱new事件--> <Child @new="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 { ref } from 'vue' const list = ref(['html', 'css', 'js']) const handle = (event) => { // event事件參數(shù),其實就是子組件發(fā)布事件時傳輸過來的值 list.value.push(event) } </script>
子組件代碼:
<template> <div class="inputGroup"> <input type="text" v-model="value"> <button @click="add">添加</button> </div> </template> <script setup> import { ref } from 'vue' const value = ref('') const emits = defineEmits(['new']) // 創(chuàng)建一個new事件 const add = () => { emits('new', value.value) // 發(fā)布事件 } </script>
子父組件通訊二
仍然是父組件展示數(shù)組信息,子組件展示輸入框用于新增數(shù)據(jù)
能用但不建議版
如果將list
數(shù)組看做成籃子,新增數(shù)據(jù)看做成蘋果,那么子父組件通訊一就是兒子把蘋果丟給父親,父親再將蘋果裝入籃中;子父組件通訊二就是父親把籃子共享給了兒子,兒子將蘋果裝入籃中
父組件定義了list
數(shù)組,通過v-model:list
指令將父組件的 list
屬性與子組件中的 list
prop 進(jìn)行了雙向綁定,意味著當(dāng)在子組件內(nèi)部修改 list 時,這些更改也會反映回父組件的 list 屬性中
子組件接收list的方式就是使用defineProps
接收
父組件代碼:
<template> <Child v-model:list="list"></Child> <div class="child"> <ul> <li v-for="item in list">{{ item }}</li> </ul> </div> </template> <script setup> import Child from '@/components/child3.vue' import { ref } from 'vue' const list = ref(['html', 'css', 'js']) </script>
子組件代碼:
<template> <div class="inputGroup"> <input type="text" v-model="value"> <button @click="add">添加</button> </div> </template> <script setup> import { ref, defineProps } from 'vue' const value = ref('') const props = defineProps({ list: { type: Array, default: () => [] } }) const add = () => { props.list.push(value.value) } </script>
但是vue官方不建議我們讓子組件直接操作父組件給過來的數(shù)據(jù),因為這樣會導(dǎo)致數(shù)據(jù)流很混亂。正常來講我自己的數(shù)組想要被修改,就應(yīng)該由我自己來改,而不是交到別人手上去改
優(yōu)化版
所以子組件的js代碼應(yīng)當(dāng)優(yōu)化成下面的樣子
使用 defineEmits
函數(shù)來聲明組件可以觸發(fā)的事件update:list
,在 Vue 中,以 update:
開頭的事件通常用于通知父組件 子組件內(nèi)部數(shù)據(jù)的變更。arr
接收list
prop 的引用,再把更新過后的arr
拋出出去,v-model:list
就會自動get到最新的值
<script setup> import { ref, defineProps } from 'vue' const value = ref('') const props = defineProps({ list: { type: Array, default: () => [] } }) const emits = defineEmits(['update:list']) const add = () => { const arr = props.list arr.push(value.value) emits('update:list', arr) } </script>
子父組件通訊三
仍然是父組件展示數(shù)組信息,子組件展示輸入框用于新增數(shù)據(jù)
父組件直接讀取到子組件更新后的list
:父組件中定義了一個響應(yīng)式變量childRef
,childRef
作為一個標(biāo)記打到子組件標(biāo)簽上,就可以通過childRef獲取到子組件的任何數(shù)據(jù)
子組件自己完成對list的更新,調(diào)用defineExpose
函數(shù),指定list
的數(shù)據(jù)可以被外部訪問
父組件代碼:
<template> <Child ref="childRef"></Child> <div class="child"> <ul> <li v-for="item in childRef?.list">{{ item }}</li> </ul> </div> </template> <script setup> import Child from '@/components/child4.vue' import { ref, onMounted } from 'vue' const childRef = ref(null) </script>
子組件代碼:
<template> <div class="inputGroup"> <input type="text" v-model="value"> <button @click="add">添加</button> </div> </template> <script setup> import { ref, defineProps } from 'vue' const value = ref('') const list = ref(['html', 'css', 'js']) const add = () => { list.value.push(value.value) } defineExpose({ list }) // 自愿暴露數(shù)據(jù) </script>
ref
是 Vue 中的一個特殊屬性,它允許我們在父組件中引用子組件或 DOM 元素
item in childRef?.list
中,?
是ES6的新語法,當(dāng)childRef有值的時候才會讀取后面的.list,沒有的時候就不會去讀取 (這樣安排是因為父組件在執(zhí)行這行代碼的時候,子組件可能還未加載完畢,這樣以免報錯)
總結(jié)
- 父子組件通訊:父組件將值
v-bind
綁定傳給子組件,子組件使用defineProps
接收 - 子組件向父組件通訊:借助發(fā)布訂閱機(jī)制,子組件負(fù)責(zé)發(fā)布事件并攜帶參數(shù),父組件訂閱該事件,通過事件參數(shù)獲取子組件提供的值
- 子組件向父組件通訊:父組件借助
v-model
將數(shù)據(jù)綁定給子組件,子組件創(chuàng)建'update:xxxx'
事件,并將接收到的數(shù)據(jù)修改后emits
出來 - 子組件向父組件通訊:父組件通過
ref
獲取子組件中defineExpose()
暴露出來的數(shù)據(jù)
以上就是vue父子組件通訊的所有方法小結(jié)的詳細(xì)內(nèi)容,更多關(guān)于vue父子組件通訊的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Vue實現(xiàn)自定義字段導(dǎo)出EXCEL的示例代碼
這篇文章主要介紹了Vue實現(xiàn)自定義字段導(dǎo)出EXCEL的示例代碼,代碼簡單易懂,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-08-08VueJs中的shallowRef與shallowReactive函數(shù)使用比較
這篇文章主要為大家介紹了VueJs中的shallowRef與shallowReactive函數(shù)的使用比較解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-04-04解決vue3中from表單嵌套el-table時填充el-input,v-model不唯一問題
這篇文章主要給大家介紹一下如何解決vue3中from表單嵌套el-table時填充el-input,v-model不唯一問題,文中有相關(guān)的解決方法,通過代碼示例介紹的非常詳細(xì),需要的朋友可以參考下2023-07-07el-descriptions引入代碼中l(wèi)abel不生效問題及解決
這篇文章主要介紹了el-descriptions引入代碼中l(wèi)abel不生效問題及解決方案,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-12-12Vue3使用src動態(tài)引入本地圖片的詳細(xì)步驟
這篇文章主要給大家介紹了關(guān)于Vue3使用src動態(tài)引入本地圖片的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2022-12-12vue3與webpack5安裝element-plus樣式webpack編譯報錯問題解決
這篇文章主要介紹了vue3與webpack5安裝element-plus樣式webpack編譯報錯,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-04-04