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

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

