vue中子組件如何間接修改父組件傳遞過來的值問題
一、前言
Vue中遵循單向數(shù)據(jù)流,所有的 props 都遵循著單向綁定原則,props 因父組件的更新而變化,自然地將新的狀態(tài)向下流往子組件,而不會(huì)逆向傳遞。
這避免了子組件意外修改父組件的狀態(tài)的情況,不然應(yīng)用的數(shù)據(jù)流將很容易變得混亂而難以理解。
但是項(xiàng)目中總是有需求讓我們來修改子組件內(nèi)部傳入的prop,所以才有了這篇文章,其實(shí)我們可以間接修改數(shù)據(jù)。
二、使用背景
父組件傳遞給子組件一個(gè)名為count數(shù)據(jù),但是現(xiàn)在要在子組件中修改它的值并且實(shí)時(shí)更新頁面,直接this.count是不能直接修改他的值的,控制臺(tái)會(huì)報(bào)錯(cuò),報(bào)錯(cuò)如下。
所以我采用了下面兩種方式間接更改。

三、解決方法
方法1
子組件通過computed計(jì)算屬性來間接修改父組件傳遞的值
父組件傳值
<GoodsBasic :renderObj='renderBasic' :count='count'></GoodsBasic>
子組件更改傳入的值
<template>
<div class='goodsBasic'>
<div>{{ incrementCount}}</div>
<button @click='changeCount'>增加次數(shù)</button>
</div>
</template>
<script>
export default {
props: {
renderObj: {
type: Object,
default () {
return {}
}
},
count:{
type: Number,
default:0
}
},
data () {
return {
increment: this.count //新定義一個(gè)變量,并把prop傳進(jìn)來的值作為初始值
}
},
computed:{
incrementCount(){ //當(dāng)新定義的變量變更時(shí),計(jì)算屬性也會(huì)自動(dòng)更新
return this.increment
}
},
methods: {
changeCount(){
this.increment++
}
}
}
</script>方法2
子組件data中重新定義個(gè)局部數(shù)據(jù),把父組件prop傳來的數(shù)據(jù)作為初始值使用。
父組件傳值
<GoodsBasic :renderObj='renderBasic' :count='count'></GoodsBasic>
子組件更改傳入的值
<template>
<div class='goodsBasic'>
<div>{{ increment }}</div>
<button @click='changeCount'>增加次數(shù)</button>
</div>
</template>
export default {
props: {
renderObj: {
type: Object,
default () {
return {}
}
},
count:{
type: Number,
default:0
}
},
data () {
return {
increment: this.count //作為初始值使用,這樣做就使prop和后續(xù)更新無關(guān)了
}
},
methods: {
changeCount(){
this.increment++
}
}
}
</script>四、更改對(duì)象 / 數(shù)組類型的 props
經(jīng)過個(gè)人測(cè)試發(fā)現(xiàn),當(dāng)傳入的prop為Object類型的時(shí)候,修改組件內(nèi)部的prop可以對(duì)應(yīng)的改變父組件中的值。
如果傳入的prop為簡(jiǎn)單類型(例如String,Number等)時(shí),瀏覽器會(huì)報(bào)錯(cuò),提示子組件不能修改prop的值。
比如上文例子更改 renderBasic.price控制臺(tái)就不會(huì)報(bào)錯(cuò)。
個(gè)人感覺當(dāng)傳入的prop為引用類型時(shí),子組件能直接修改父組件值,是因?yàn)樵诙褍?nèi)存中公用同一個(gè)內(nèi)存地址;修改的話只是改了它的值,而內(nèi)存地址并沒變,所以不報(bào)錯(cuò);
基本數(shù)據(jù)類型修改會(huì)報(bào)錯(cuò),原因是指向的內(nèi)存地址要被迫修改,所以控制臺(tái)報(bào)錯(cuò)。
另外Vue官方文檔也說了:
- 當(dāng)對(duì)象或數(shù)組作為 props 被傳入時(shí),雖然子組件無法更改 props 綁定,但仍然可以更改對(duì)象或數(shù)組內(nèi)部的值。
- 這是因?yàn)?JavaScript 的對(duì)象和數(shù)組是按引用傳遞,而對(duì) Vue 來說,禁止這樣的改動(dòng),雖然可能生效,但有很大的性能損耗,比較得不償失。
- 這種更改的主要缺陷是它允許了子組件以某種不明顯的方式影響父組件的狀態(tài),可能會(huì)使數(shù)據(jù)流在將來變得更難以理解。在最佳實(shí)踐中,你應(yīng)該盡可能避免這樣的更改,除非父子組件在設(shè)計(jì)上本來就需要緊密耦合。
- 在大多數(shù)場(chǎng)景下,子組件應(yīng)該拋出一個(gè)事件來通知父組件做出改變。
目前我們公司有個(gè)項(xiàng)目就是就是因?yàn)楦缸咏M件數(shù)據(jù)需要緊密耦合的,所以直接在子組件更改了數(shù)據(jù);
上面文檔說的子組件應(yīng)該拋出一個(gè)事件來通知父組件做出改變,意思就是子組件調(diào)用$emit拋出一個(gè)事件名,去通知父組件,值要改變了,在父組件寫一個(gè)事件做后續(xù)處理。
想繼續(xù)深入vue傳值的問題,也可以去看我之前關(guān)于vue中傳值方法的文章。
vue組件之間的傳值方法(父子傳值,兄弟傳值,跨級(jí)傳值,vuex)
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Vue中component標(biāo)簽解決項(xiàng)目組件化操作
這篇文章主要介紹了Vue中component標(biāo)簽解決項(xiàng)目組件化操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-09-09
vue3.0+vite2實(shí)現(xiàn)動(dòng)態(tài)異步組件懶加載
學(xué)了vue寫項(xiàng)目這么久,忽然發(fā)現(xiàn)路由懶加載的寫法,節(jié)省了加載所有路由的時(shí)間。本文主要介紹了vue3.0+vite2實(shí)現(xiàn)動(dòng)態(tài)異步組件懶加載,感興趣的可以了解一下2021-06-06
vue使用ECharts實(shí)現(xiàn)折線圖和餅圖
這篇文章主要為大家詳細(xì)介紹了vue使用ECharts實(shí)現(xiàn)折線圖和餅圖,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-09-09
php+vue3實(shí)現(xiàn)點(diǎn)選驗(yàn)證碼功能
這篇文章主要介紹了php+vue3實(shí)現(xiàn)點(diǎn)選驗(yàn)證碼,本文通過實(shí)例代碼給大家介紹的詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2023-11-11
Vue3路由跳轉(zhuǎn)并傳遞參數(shù)的應(yīng)用場(chǎng)景分析
本文主要介紹在Vue3工程使用setup語法中如何進(jìn)行路由跳轉(zhuǎn)并傳遞參數(shù),本文結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2025-05-05
Vue使用三方工具vueUse實(shí)現(xiàn)虛擬列表
其實(shí)采用vueUse中的useVirtualList方法同樣可以實(shí)現(xiàn)虛擬列表,這篇文章小編就來和大家詳細(xì)介紹一下如何使用vueUse實(shí)現(xiàn)簡(jiǎn)單的虛擬列表效果吧2024-04-04

